-
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ärkeimpiin abstraktioihin, 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 mukanaan myös joitakin omia lisäobjektejaan.
Kubernetes-käsitteet
Nimiavaruus
Jokainen Kubernetes-objekti luodaan nimiavaruuden sisään. 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 luomiseksi katso ohje 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ämiseen. Jokaisella podilla on oma IP-osoitteensa, jonka kaikki podin kontit jakavat. Tämä IP-osoite voi muuttua, jos podi tapetaan 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 tappaa 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 poistamisen jälkeen, tulee tallentaa podiin liitetylle pysyvälle taltiolle.

Kubernetesin/OpenShiftin abstraktiot kuvataan YAMLin tai JSONin avulla. YAML ja JSON ovat niin sanottuja datan serialisointikieliä, 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 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 verkkopalvelinpodin, 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ä 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 kuormantasaimina 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ä tiedonsiirtoprotokolla (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 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 vaiheittaisia päivityksiä. Ne sisältävät tyypillisesti ReplicaSetin ja useita podeja. Jos teet muutoksen, joka vaatii päivityksen, kuten podikonttien uudemman levykuvan käyttöönoton, deployment varmistaa, että muutos tehdään ilman palvelukatkoksia. Se suorittaa vaiheittaisen päivityksen tappamalla podit yksi kerrallaan ja korvaamalla ne 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 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-levykuvaa ja odottaa, että app-BuildConfigin build päättyy. Kun se päättyy, normaali kontti voidaan käynnistää tietäen, että levykuva 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 vaiheittainen julkaisustrategia. Kun uusi levykuva otetaan käyttöön, Kubernetes tappaa 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. 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 vaiheittaiset 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-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 taltioliitosten avulla.
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-objektimääritys, 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.
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-objektimäärityksestä.
Yllä secret.yaml-tiedostona esitetystä määrityksestä 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ääritys, 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 konttilevykuvia lähdetiedostojen perusteella.
- ImageStream-objektit abstrahoivat levykuvia ja rikastavat ne virroiksi, jotka lähettävät signaaleja havaitessaan, että niihin on ladattu uusi levykuva esimerkiksi BuildConfigin toimesta.
- Route-objektit yhdistävät Service-objektin 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 vaiheittaisen päivityksen, kun sen laukaisee ImageStream nimeltä
serveimagestream:latest. Muita päivitysstrategioita varten katso OpenShift-dokumentaation kohta "Deployment
Strategies".
DeploymentConfig-objektit toimivat samankaltaisesti kuin luvussa
deployment kuvatut deploymentit, paitsi että deploymentit
laukaisevat päivityksiä vain, kun spec.template muuttuu. Lisäksi deployment
on puhdas Kubernetes-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 levykuvia. Ne yksinkertaistavat konttilevykuvien hallintaa, ja niitä voi luoda BuildConfig tai käyttäjä, kun uusia levykuvia 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 konttilevykuvia tiettyjen sääntöjen mukaisesti. Seuraavassa esimerkissä käytetään Docker-strategiaa rakentamaan triviaalinen laajennus
OpenShiftin mukana toimitetusta httpd-levykuvasta.
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 levykuvan:
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ääritys 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 lähettäen sen palveluun selväkielisenä. Muitatermination-asetuksen vaihtoehtoja ovatpassthroughjareencrypt.
Jokaiselle isäntänimelle, joka vastaa mallia *.2.rahtiapp.fi tai *.rahtiapp.fi, luodaan automaattisesti DNS-tietue ja voimassa oleva TLS-varmenne. Route on mahdollista määrittää mille tahansa isäntänimelle, 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.
Oletusisäntänimi
Oletuksena Routen isäntänimi on metadata.name + - + projektin nimi + .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.