-
Kubernetes- ja OpenShift-käsitteet
Kubernetesin ja OpenShiftin käsitteet
Kubernetesin (ja OpenShiftin) voima perustuu suhteellisen yksinkertaisiin abstraktioihin, joita ne tarjoavat monimutkaisiin tehtäviin, kuten kuormantasaamiseen, hajautetun järjestelmän ohjelmistopäivityksiin tai automaattiseen skaalaukseen. Tässä annamme hyvin lyhyen yleiskatsauksen joihinkin tärkeimmistä abstraktioista, mutta suosittelemme vahvasti, että luet myös Kubernetesin ja OpenShiftin käsitedokumentaation:
Nämä abstraktiot ovat objekteja, pysyviä entiteettejä Kubernetes-järjestelmässä. Näitä entiteettejä käytetään edustamaan projektin haluttua tilaa (jota Kubernetesissa kutsutaan myös nimiavaruudeksi). Suurin osa objekteista on yhteisiä sekä tavalliselle Kubernetesille että OpenShiftille, mutta OpenShift tuo mukanaan myös joitakin omia lisäobjektejaan.
Kubernetesin käsitteet
Nimiavaruus
Jokainen Kubernetes-objekti luodaan nimiavaruuden sisälle. Se on yksinkertaisesti hiekkalaatikko, jossa kaikki muut objektit sijaitsevat ja ovat erotettuina muihin nimiavaruuksiin kuuluvista objekteista. OpenShiftissä niistä käytetään nimitystä projektit. Nämä kaksi nimeä (projekti ja nimiavaruus) ovat tietotekniikassa hyvin yleisiä sanoja, joten niihin viittaaminen voi joskus olla hämmentävää. Projektin luomisesta kerrotaan dokumentaatiossa Projektin luominen.
Podi
Podit sisältävät yhden tai useamman kontin, joissa ajetaan sovelluksia. Se on Kubernetesin perusyksikkö: kun ajat työkuorman Kubernetesissa, se ajetaan aina podissa. Kubernetes huolehtii näiden podien ajastamisesta useille palvelimille. Podit voivat sisältää erityyppisiä taltioita datan käyttämistä varten. Jokaisella podilla on oma IP-osoitteensa, joka on kaikkien podin konttien yhteinen. Tämä IP-osoite voi muuttua, jos podi tuhotaan ja luodaan uudelleen. Tyypillisimmässä tapauksessa podi sisältää yhden kontin ja ehkä yhden tai muutaman erilaisen taltioin.
Podit on tarkoitettu kertakäyttöisiksi, eli ne voidaan tuhota milloin tahansa, ja "pilvinatiivin" sovelluksen on pystyttävä jatkamaan toimintaansa ilman, että käyttäjä huomaa keskeytystä. Sen on palaututtava automaattisesti. Kaikki data, jonka täytyy säilyä podin tuhoamisen jälkeen, tulee tallentaa podiin liitetylle pysyvälle taltiolle.

Kubernetesin/OpenShiftin abstraktiot kuvataan YAML- tai JSON-muodossa. YAML ja JSON ovat niin sanottuja datasarjallistuskieliä, jotka tarjoavat tavan kuvata avain-arvo-pareja ja tietorakenteita, kuten listoja, tavalla, joka on helppo lukea sekä ihmisille että tietokoneille. Esimerkki siitä, miltä podin esitys näyttää YAML-muodossa:
---
apiVersion: v1
kind: Pod
metadata:
name: name
spec:
containers:
- name: webserver
image: cscfi/nginx-okd
ports:
- containerPort: 8080
protocol: TCP
volumeMounts:
- name: website-content-volume
mountPath: /usr/share/nginx/html
volumes:
- name: website-content-volume
persistentVolumeClaim:
claimName: web-content-pvc
Yllä oleva YAML-esitys kuvaa verkkopalvelinpodia, jossa on yksi kontti ja yksi taltio ja joka avaa portin 8080. Voisit sijoittaa tämän tekstikatkelman tiedostoon ja luoda podin, joka ajaa NGINX:iä, syöttämällä tiedoston Kubernetes API:lle.
Palvelu
Podien IP-osoitteet eivät ole ennustettavia. Jos podi korvataan osana normaaleja toimintoja, kuten päivitystä, uuden podin IP-osoite voi olla eri. On myös tyypillistä, että useat podit tarjoavat samaa sisältöä, jolloin osoitettavana on useita tällaisia ennustamattomia IP-osoitteita. Siksi pelkät podit eivät riitä tarjoamaan ennustettavaa tapaa käyttää sovellusta.
Palvelu tarjoaa vakaan virtuaalisen IP-osoitteen, portin ja DNS-nimen yhdelle tai useammalle podille. Ne toimivat kuormantasaajina ja ohjaavat liikenteen podiryhmälle, joka kaikki palvelevat samaa sovellusta.

service.yaml:
apiVersion: v1
kind: Service
metadata:
labels:
app: app
name: service-name
spec:
ports:
- name: 8080-tcp
port: 8080
protocol: TCP
targetPort: 8080
selector:
app: app
sessionAffinity: None
type: ClusterIP
status:
loadBalancer: {}
Portit
-
Kubernetes-palvelun
ports-kenttä määrittää verkkportit, jotka palvelu avaa asiakkaille, ja miten ne yhdistetään podien vastaaviin portteihin. -
Se koostuu tyypillisesti useista osista:
- Nimi: Portin tunniste, joka voi helpottaa sen tunnistamista.
- Portti: Porttinumero, jota asiakkaat käyttävät palvelun käyttämiseen.
- Protokolla: Käytettävä viestintäprotokolla (yleensä TCP).
- TargetPort: Podin portti, johon palvelu ohjaa liikenteen.
Valitsin
-
Kubernetes-palvelun
selector-kenttä on keskeinen sen määrittämisessä, mihin podeihin palvelun tulee ohjata liikennettä. -
Se koostuu avain-arvo-pareista, jotka vastaavat podeille annettuja tunnisteita. Palvelu käyttää näitä tunnisteita tunnistaakseen ja yhdistääkseen oikeisiin podeihin dynaamisesti.
-
Avain-arvo-pari (
app: app): Tämä tarkoittaa, että palvelu ohjaa liikenteen kaikkiin podeihin, joilla on tunnisteapp: app. -
Toiminnallisuus: Tämä mahdollistaa sen, että palvelu yhdistyy automaattisesti kaikkiin olennaisiin podeihin. Jos tällä tunnisteella varustettuja podeja lisätään tai poistetaan, palvelu mukauttaa reititystään vastaavasti ja varmistaa, että liikenne ohjataan aina oikeisiin podeihin.
ReplicaSet
ReplicaSet varmistaa, että podista on käynnissä n kopiota. Jos yksi podeista kuolee, ReplicaSet varmistaa, että sen tilalle luodaan uusi. Niitä ei yleensä käytetä sellaisenaan, vaan osana Deploymentia (selitetään seuraavaksi).

Deployment
Deploymentit hallitsevat sovelluksen liukuvia päivityksiä. Ne sisältävät tyypillisesti ReplicaSetin ja useita podeja. Jos teet muutoksen, joka vaatii päivityksen, kuten siirtymisen uudempaan konttikuvaan podin konteille, deployment varmistaa, että muutos tehdään niin, ettei palvelukatkoksia synny. Se suorittaa liukuvan päivityksen, jossa kaikki podit lopetetaan yksi kerrallaan ja korvataan uudemmilla samalla varmistaen, että loppukäyttäjien liikenne ohjataan koko ajan toimiviin podeihin.

InitContainer
InitContainer on podissa oleva kontti, jonka on tarkoitus suorittaa loppuun ennen kuin pääkontit käynnistetään. Dataa init-konteista voidaan siirtää pääkonttiin esimerkiksi tyhjien taltioiden liitosten avulla.
pod-init.yaml:
apiVersion: v1
kind: ServiceAccount
metadata:
name: build-reader
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: build-reader
rules:
- apiGroups:
- build.openshift.io
resources:
- builds
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: build-reader
subjects:
- kind: ServiceAccount
name: build-reader
roleRef:
kind: Role
name: build-reader
apiGroup: rbac.authorization.k8s.io
---
apiVersion: v1
kind: Pod
metadata:
name: mypod
labels:
app: serveapp
pool: servepod
spec:
volumes:
- name: sharevol
emptyDir: {}
initContainers:
- name: perlhelper
imagePullPolicy: IfNotPresent
image: quay.io/openshift/origin-cli:4.16
command:
- sh
- -c
- "oc wait --for=jsonpath='{.status.phase}'=Complete build -l buildconfig=app --timeout=900s"
containers:
- name: serve-cont
image: image-registry.apps.2.rahti.csc.fi/project/app
volumeMounts:
- mountPath: /var/www/html
name: sharevol
Tässä ajamme init-kontin, joka käyttää origin-cli-kuvaa ja odottaa, että app-BuildConfigin build päättyy. Kun se päättyy, normaali kontti voidaan käynnistää tietäen, että kuva on jo luotu.
Jaettu taltio määritellään kohdassa spec.volumes ja "liitetään" kohdissa spec.initContainers[].volumeMounts ja spec.containers[].volumeMounts.
StatefulSet
Useimmat Kubernetes-objektit ovat tilattomia. Tämä tarkoittaa, että ne voidaan poistaa ja luoda uudelleen, ja sovelluksen pitäisi pystyä käsittelemään tämä ilman näkyvää vaikutusta. Esimerkiksi Deployment määrittää podin, jossa on 5 replikaa ja liukuva julkaisustrategia. Kun uusi kuva otetaan käyttöön, Kubernetes lopettaa kaikki podit yksi kerrallaan ja luo ne uudelleen eri nimillä ja mahdollisesti eri noodeihin, pitäen aina vähintään 5 replikaa aktiivisena. Joillekin sovelluksille tämä ei ole hyväksyttävää, ja tätä käyttötapausta varten on luotu StatefulSetit.
Kuten Deployment, myös StatefulSet määrittää podit konttimäärityksen perusteella. Mutta toisin kuin Deployment, StatefulSet antaa odotetun ja vakaan identiteetin, jossa on pysyvä tunniste, joka säilyy kaikissa tapahtumissa (päivitykset, uudelleenkäyttöönotot, ...). StatefulSet tarjoaa:
- Vakaat, yksilölliset verkkotunnisteet.
- Vakaan, pysyvän tallennuksen.
- Järjestetyn, hallitun käyttöönoton ja skaalauksen.
- Järjestetyt, automatisoidut liukuvat päivitykset.
statefulSet.yaml:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
selector:
matchLabels:
app: nginx # has to match .spec.template.metadata.labels
serviceName: "nginx"
replicas: 3 # If omitted, by default is 1
template:
metadata:
labels:
app: nginx # has to match .spec.selector.matchLabels
spec:
terminationGracePeriodSeconds: 10
containers:
- name: nginx
image: openshift/hello-openshift
ports:
- containerPort: 8888
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "standard-csi"
resources:
requests:
storage: 1Gi
Jobit
Job käyttää podeja tietyn tehtävän suorittamiseen yhden tai useamman kerran ja yrittää podien suorittamista uudelleen, kunnes määritetty määrä niistä päättyy onnistuneesti tai backoff-raja saavutetaan. Kun podit valmistuvat onnistuneesti, Job seuraa onnistuneita valmistumisia. Kun määritetty määrä onnistuneita valmistumisia saavutetaan, tehtävä (eli Job) on valmis. Jobin poistaminen siivoaa sen luomat podit. Jobin keskeyttäminen poistaa sen aktiiviset podit, kunnes Jobia jatketaan uudelleen.
job.yaml:
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
template:
spec:
volumes:
- name: smalldisk-vol
emptyDir: {}
containers:
- name: pi
image: perl
command:
- sh
- -c
- >
echo helloing so much here! Lets hello from /mountdata/hello.txt too: &&
echo hello to share volume too >> /mountdata/hello-main.txt &&
cat /mountdata/hello.txt
volumeMounts:
- mountPath: /mountdata
name: smalldisk-vol
restartPolicy: Never
initContainers:
- name: init-pi
image: perl
command:
- sh
- -c
- >
echo this hello is from the initcontainer >> /mountdata/hello.txt
volumeMounts:
- mountPath: /mountdata
name: smalldisk-vol
backoffLimit: 4
Tämä Job nimeää podin automaattisesti, ja podia voidaan hakea job-name-tunnisteella:
Jobin vakiotuloste:
$ oc logs pi-gj7xg
helloing so much here! Lets hello from /mountdata/hello.txt too:
this hello is from the initcontainer
Projektin nimiavaruudessa voi olla vain yksi objekti tietyllä nimellä, joten Jobia ei voi ajaa kahdesti, ellei sen ensimmäistä instanssia poisteta. Podia ei kuitenkaan tarvitse siivota, sillä se poistetaan automaattisesti ketjussa Jobin poistamisen jälkeen.
ConfigMap
ConfigMapit ovat hyödyllisiä konfiguraatiotyyppisen datan kokoamisessa Kubernetes-objekteihin. Niiden sisältö välitetään konteille ympäristömuuttujien tai taltioiden liitosten kautta.
configmap.yaml:
kind: ConfigMap
apiVersion: v1
metadata:
name: my-config-map
data:
data.prop.a: hello
data.prop.b: bar
data.prop.long: |-
fo=bar
baz=notbar
Luo ConfigMap
ConfigMapeja voidaan luoda eri tavoilla. Jos meillä on yllä configmap.yaml-tiedostossa esitetty ConfigMap-objektin määritelmä, siitä voidaan luoda instanssi komennolla oc create -f configmap.yaml. Voit myös käyttää tarkempaa komentoa oc create configmap <configmap_name> [options] luodaksesi ConfigMap-instanssin hakemistoista, tietyistä tiedostoista tai literaaliarvoista.
Esimerkiksi jos sinulla on hakemisto, jossa on tiedostoja ja joka sisältää ConfigMapin täyttämiseen tarvittavan datan seuraavasti:
Voit sitten luoda ConfigMapin, joka on samanlainen kuin configmap.yaml-tiedostossa määritelty, näin:
Tämä komento toimii myös tiedostojen kanssa hakemistojen sijaan.
Käytä ConfigMapia
Seuraava podi tuo arvon data.prop.a ympäristömuuttujaan DATA_PROP_A ja luo tiedostot data.prop.a, data.prop.b ja data.prop.long hakemistoon /etc/my-config:
configmap-pod.yaml:
kind: Pod
apiVersion: v1
metadata:
name: my-config-map-pod
spec:
restartPolicy: Never
volumes:
- name: configmap-vol
configMap:
name: my-config-map
containers:
- name: confmap-cont
image: perl
command:
- /bin/sh
- -c
- |-
cat /etc/my-config/data.prop.long &&
echo "" &&
echo DATA_PROP_A=$DATA_PROP_A
env:
- name: DATA_PROP_A
valueFrom:
configMapKeyRef:
name: my-config-map
key: data.prop.a
optional: true # Run this pod even
volumeMounts: # if data.prop.a is not defined in configmap
- name: configmap-vol
mountPath: /etc/my-config
Ota podi käyttöön komennolla oc create -f configmap-pod.yaml. Tämän kontin tulostelokin, joka saadaan komennolla oc logs my-config-map-pod, pitäisi olla:
Secret
Secretit toimivat pitkälti samalla tavalla kuin ConfigMapit, sillä erotuksella, että luomisen jälkeen ne tallennetaan base64-koodatussa muodossa, eikä niiden sisältöä näytetä oletusarvoisesti komentorivillä tai selainkäyttöliittymässä.
secret.yml:
apiVersion: v1
kind: Secret
data:
WebHookSecretKey: dGhpc19pc19hX2JhZF90b2tlbgo=
metadata:
name: webhooksecret
Luo secret
Kuten muutkin OpenShift/Kubernetes-objektit, myös Secretit voidaan luoda Secret-objektin määritelmästä.
Yllä secret.yaml-tiedostona esitetystä määritelmästä voidaan luoda Secret-instanssi komennolla oc create -f secret.yaml. Voit myös käyttää tarkempaa komentoa oc create secret [flags] <secret_name> [options]
luodaksesi Secret-instanssin hakemistoista, tietyistä tiedostoista tai literaaliarvoista.
Jos sinulla on esimerkiksi tiedosto nimeltä WebHookSecretKey, joka sisältää salaisen avaimen, voit
käyttää sitä luodaksesi Secret-instanssin, joka on samanlainen kuin aiemmassa secret.yaml-tiedostossa määritelty, seuraavasti:
Muokkaa secretiä
Secretin muokkausprosessi ei ole suoraviivainen. Ajatuksena on hakea Secretin JSON-määritelmä, purkaa se, muokata sitä ja sitten koodata se uudelleen ja korvata alkuperäinen.
- Ensin sinun täytyy hakea Secretin sisältämät eri tiedostot/salaisuudet (esimerkeissä käytetään
jq:ta JSON-tiedostojen käsittelyyn, mutta tämä onnistuu myös ilman sitä):
- Valitse sitten yksi vaihtoehdoista ja hae itse tiedosto/salaisuus:
oc get secrets <SECRET_NAME> -o json >secret.json
jq '.data.<KEY_NAME>' -r secret.json | base64 -d > <KEY_NAME>.file
-
Muokkaa tiedostoa haluamallasi editorilla.
-
Koodaa uusi tiedosto ja korvaa aiempi arvo JSON-tiedostossa:
B64=$(base64 <KEY_NAME>.file -w0)
jq " .data.<KEY_NAME> = \"$B64\" " secret.json
oc replace -f secret.json
Kuten huomaat, prosessi voi olla hieman hankalasti hahmotettava.
OpenShift-laajennukset
OpenShift sisältää kaikki Kubernetes-objektit sekä joitakin laajennuksia:
- BuildConfig-objektit rakentavat konttikuvia lähdetiedostojen perusteella.
- ImageStream-objektit abstrahoivat kuvia ja rikastavat ne virroiksi, jotka lähettävät signaaleja, kun niihin ladataan uusi kuva esimerkiksi BuildConfigin toimesta.
- Route-objektit yhdistävät palvelun internetiin HTTP:n avulla.
DeploymentConfig
Warning
OKD 4.14:stä alkaen DeploymentConfig API poistuu käytöstä. Tulevaisuudessa korjataan vain tietoturvaan liittyviä ja kriittisiä ongelmia. Lisätietoja täältä ja DeploymentConfigin korvausoppaasta.
DeploymentConfigit ovat objekteja, jotka luovat
ReplicationControllereita kohdan
spec.template mukaisesti. Ne eroavat ReplicationControllereista siinä, että
DeploymentConfig-objektit voivat käynnistää uusia ReplicationControllereita kohdan
spec.triggers tilan perusteella. Alla olevassa esimerkissä DeploymentConfig suorittaa
automaattisen liukuvan päivityksen, kun sen laukaisee serveimagestream:latest-niminen
ImageStream. Muita päivitysstrategioita varten katso "Deployment
Strategies"
OpenShiftin dokumentaatiosta.
DeploymentConfig-objektit toimivat samankaltaisesti kuin luvussa
deployment kuvatut deploymentit, paitsi että deploymentit
laukaisevat päivityksiä vain, kun spec.template muuttuu. Lisäksi deployment
on puhtaasti Kubernetesin käsite, ja DeploymentConfig on OpenShift-laajennus.
Muista, että ReplicationControllerit
ovat objekteja, jotka varmistavat, että pyydetty määrä spec.template-kohdassa määritellyn podin replikoita on käynnissä.
deploymentconfig.yaml:
apiVersion: apps.openshift.io/v1
kind: DeploymentConfig
metadata:
labels:
app: serveapp
name: blogdeployment
spec:
replicas: 1
selector:
app: serveapp
deploymentconfig: blogdeployment
strategy:
activeDeadlineSeconds: 21600
type: Rolling
template:
metadata:
labels:
app: serveapp
deploymentconfig: blogdeployment
spec:
containers:
- name: serve-cont
image: "serveimagestream:latest"
triggers:
- type: ConfigChange
- imageChangeParams:
automatic: true
containerNames:
- serve-cont
from:
name: serveimagestream:latest
type: ImageChange
Tässä tapauksessa DeploymentConfig-objekti kuuntelee ImageStream-objektia
serveimagestream:latest.
ImageStream
ImageStreamit tallentavat kuvia. Ne yksinkertaistavat konttikuvien hallintaa, ja niitä voi luoda BuildConfig tai käyttäjä, kun uusia kuvia ladataan rekisteriin.
Yksinkertainen ImageStream-objekti:
imagestream.yaml:
apiVersion: image.openshift.io/v1
kind: ImageStream
metadata:
labels:
app: serveapp
name: serveimagestream
spec:
lookupPolicy:
local: false
BuildConfig
BuildConfig -objektit
luovat konttikuvia tiettyjen sääntöjen mukaisesti. Seuraavassa esimerkissä käytetään Docker-strategiaa rakentamaan triviaalinen laajennus OpenShiftin mukana toimitetusta httpd-kuvasta.
buildconfig.yaml:
kind: "BuildConfig"
apiVersion: "build.openshift.io/v1"
metadata:
name: "serveimg-generate"
labels:
app: "serveapp"
spec:
runPolicy: "Serial"
output:
to:
kind: ImageStreamTag
name: serveimagestream:latest
source:
dockerfile: |
FROM image-registry.openshift-image-registry.svc:5000/openshift/httpd
strategy:
type: Docker
Kun build-objekti (tässä nimeltään serveimg-generate) on luotu, voimme
pyytää OpenShift-klusteria rakentamaan kuvan:
Muita lähdestrategioita ovat custom, jenkins ja source.
Route
Route-objektit ovat OpenShiftin vastine tavallisen Kubernetesin Ingressille; ne avaavat Service-objektin internetiin HTTP/HTTPS:n kautta. Tyypillinen Route-määritelmä voisi olla:
apiVersion: route.openshift.io/v1
kind: Route
metadata:
name: <name-of-the-route>
spec:
host: <host.name.dom>
to:
kind: Service
weight: 100
name: <name-of-service>
tls:
insecureEdgeTerminationPolicy: Redirect
termination: edge
status:
ingress: []
Tämä ohjaa kaiken osoitteeseen <host.name.dom> tulevan liikenteen palveluun name-of-service.
insecureEdgeTerminationPolicyon asetettu arvoonRedirect. Tämä tarkoittaa, että kaikki porttiin 80 (HTTP) tuleva liikenne ohjataan porttiin 443 (HTTPS).terminationon asetettu arvoonedge. Tämä tarkoittaa, että route hallitsee TLS-varmennetta ja purkaa liikenteen salauksen ennen sen lähettämistä palveluun selväkielisenä. Muitatermination-asetuksen vaihtoehtoja ovatpassthroughjareencrypt.
Jokaisella hostilla, joka vastaa mallia *.2.rahtiapp.fi tai *.rahtiapp.fi, on automaattisesti DNS-tietue ja voimassa oleva TLS-varmenne. Route on mahdollista määrittää millä tahansa hostnimellä, mutta tällöin on määritettävä CNAME, joka osoittaa osoitteeseen router.2.rahtiapp.fi, ja lisäksi on toimitettava TLS-varmenne. Katso lisätietoja artikkelista Mukautetut verkkotunnukset ja suojattu tiedonsiirto.
Oletushostnimi
Oletuksena Routen hostnimi on metadata.name + - + project name + .2.rahtiapp.fi, ellei kohdassa spec.host ole määritetty muuta.
IP-sallintalistaus
Annotaatioita voidaan käyttää IP-sallintalistauksen ottamiseen käyttöön, jolloin vain tietyt IP-alueet saavat kulkea Routen läpi ja muu internet estetään. Tietoturvan kannalta on erittäin suositeltavaa hyödyntää IP-sallintalistaa palveluille, joiden ei ole tarkoitus näkyä koko internetiin. Lisää se routeen näin:
Warning
Vanha ip_whitelist-annotaatio on poistumassa käytöstä, mutta sitä tuetaan edelleen yhteensopivuuden vuoksi.
Se poistetaan tulevassa versiossa.
Warning
Jos sallintalistan merkintä on virheellinen, OpenShift hylkää sallintalistan ja sallii kaiken liikenteen.