-
Kubernetes- ja OpenShift-käsitteet
Kubernetes- ja OpenShift-käsitteet
Kubernetesin (ja OpenShiftin) voima perustuu niiden tarjoamiin suhteellisen yksinkertaisiin abstraktioihin 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 kuvaamaan projektin haluttua tilaa (jota Kubernetesissa kutsutaan myös nimiavaruudeksi). Suurin osa objekteista on yhteisiä sekä tavalliselle Kubernetesille että OpenShiftille, mutta OpenShift tuo lisäksi mukanaan joitakin omia lisäobjektejaan.
Kubernetes-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. Molemmat nimet (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 sovelluksia ajavan kontin. 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-osoite, joka on kaikkien podin konttien yhteinen. Tämä IP-osoite voi muuttua, jos podi lopetetaan ja luodaan uudelleen. Tyypillisimmässä tapauksessa podi sisältää yhden kontin ja ehkä yhden tai muutaman eri taltion.
Podit on tarkoitettu kertakäyttöisiksi, eli ne voidaan lopettaa 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 lopettamisen jälkeen, tulee tallentaa podiin liitetylle pysyvälle taltiolle.

Kubernetesin/OpenShiftin abstraktiot kuvataan YAMLilla tai JSONilla. YAML ja JSON ovat niin sanottuja datan serialisointikieliä, jotka tarjoavat tavan kuvata avain-arvo-pareja ja tietorakenteita, kuten listoja, tavalla, joka on helppolukuinen sekä ihmisille että tietokoneille. Esimerkki siitä, miltä podin esitys YAML-muodossa näyttää:
---
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 tallentaa tämän tekstikatkelman tiedostoon ja luoda podin, joka ajaa NGINXiä, 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 tavallista, että samaa sisältöä palvelee useita podeja, 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:
- Name: Portin nimiö, joka voi auttaa sen tunnistamisessa.
- Port: Porttinumero, jota asiakkaat käyttävät palvelun käyttämiseen.
- Protocol: 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 liikenne. -
Se koostuu avain-arvo-pareista, jotka vastaavat podeille annettuja nimiöitä. Palvelu käyttää näitä nimiöitä tunnistaakseen ja yhdistääkseen oikeisiin podeihin dynaamisesti.
-
Avain-arvo-pari (
app: app): Tämä tarkoittaa, että palvelu ohjaa liikenteen kaikkiin podeihin, joilla on nimiöapp: app. -
Toiminnallisuus: Tämä mahdollistaa sen, että palvelu yhdistyy automaattisesti kaikkiin olennaisiin podeihin. Jos tällä nimiöllä varustettuja podeja lisätään tai poistetaan, palvelu mukauttaa reititystään vastaavasti ja varmistaa, että liikenne ohjautuu 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 podien konttien vaihtamisen uudempaan imageen, deployment varmistaa, että muutos tehdään ilman palvelukatkoksia. Se suorittaa liukuvan päivityksen, jossa kaikki podit lopetetaan yksi kerrallaan ja korvataan uudemmilla samalla varmistaen, että loppukäyttäjien liikenne ohjautuu 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 taltioliitosten 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-imagea ja odottaa, että app-BuildConfigin build valmistuu. Kun se päättyy, tavallinen kontti voidaan käynnistää tietäen, että image 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 image otetaan käyttöön, Kubernetes lopettaa kaikki podit yksi kerrallaan ja luo ne uudelleen eri nimillä ja mahdollisesti eri solmuissa 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 sekä pysyvän tunnisteen, 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 suorituksia. Kun määritetty määrä onnistuneita suorituksia 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-nimiöllä:
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 kokoamiseen Kubernetes-objekteihin. Niiden sisältö välitetään konteille ympäristömuuttujien tai taltioliitosten 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
ConfigMapin luominen
ConfigMapeja voidaan luoda eri tavoilla. Jos meillä on yllä configmap.yaml-tiedostossa esitetty ConfigMap-objektin määrittely, 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, jonka tiedostot sisältävät ConfigMapin täyttämiseen tarvittavan datan seuraavasti:
Voit sitten luoda configmap.yaml-tiedostossa määritellyn kaltaisen ConfigMapin näin:
Tämä komento toimii myös tiedostojen kanssa hakemistojen sijaan.
ConfigMapin käyttäminen
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
Secretin luominen
Kuten muutkin OpenShift/Kubernetes-objektit, myös Secretit voidaan luoda Secret-objektin määrittelystä.
Yllä secret.yaml-tiedostona esitetystä määrittelystä 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:
Secretin muokkaaminen
Secretin muokkausprosessi ei ole aivan suoraviivainen. Ajatuksena on hakea Secretin JSON-määrittely, 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/secretit (esimerkeissä käytetään
jq:ta JSON-tiedostojen käsittelyyn, mutta tämän voi tehdä myös ilman sitä):
- Valitse sitten yksi vaihtoehdoista ja hae itse tiedosto/secret:
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 näet, prosessi voi olla hieman hankalasti hahmotettava.
OpenShift-laajennukset
OpenShift sisältää kaikki Kubernetes-objektit sekä joitakin laajennuksia:
- BuildConfig-objektit rakentavat kontti-imageja lähdetiedostojen perusteella.
- ImageStream-objektit abstrahoivat imaget ja rikastavat ne virroiksi, jotka lähettävät signaaleja havaitessaan, että niihin on esimerkiksi BuildConfigin toimesta ladattu image.
- 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äällä ja DeploymentConfigin korvausoppaassa.
DeploymentConfigit ovat objekteja, jotka luovat
ReplicationControllerit 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 ImageStream nimeltä
serveimagestream:latest. Muista päivitysstrategioista kerrotaan kohdassa "Deployment
Strategies"
OpenShift-dokumentaatiossa.
DeploymentConfig-objektit toimivat samankaltaisesti kuin luvussa
deployment kuvatut deploymentit, paitsi että deploymentit
käynnistävät päivitykset vain, kun spec.template muuttuu. Lisäksi deployment
on puhtaasti Kubernetes-käsite, kun taas DeploymentConfig on OpenShift-laajennus.
Muista, että ReplicationControllerit
ovat objekteja, jotka varmistavat, että määritelty määrä kohdassa
spec.template 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 imageja. Ne yksinkertaistavat kontti-imagejen hallintaa, ja niitä voi luoda BuildConfig tai käyttäjä, kun uusia imageja 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 kontti-imageja tiettyjen sääntöjen mukaisesti. Seuraavassa esimerkissä käytetään Docker-strategiaa triviaalin laajennuksen rakentamiseen
OpenShiftin mukana toimitetusta httpd-imagesta.
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 on luotu (tässä nimeltään serveimg-generate), voimme
pyytää OpenShift-klusteria rakentamaan imagen:
Muita lähdestrategioita ovat custom, jenkins ja source.
Route
Route-objektit ovat OpenShiftin vastine Ingressille tavallisessa Kubernetesissa. Ne avaavat Service-objektin internetiin HTTP/HTTPS:n kautta. Tyypillinen Route-määrittely 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 liikenteen, joka tulee osoitteeseen <host.name.dom>, 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-vaihtoehtoja ovatpassthroughjareencrypt.
Jokaiselle hostille, joka vastaa mallia *.2.rahtiapp.fi tai *.rahtiapp.fi, luodaan 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 muutama IP-alue saa 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.