kubectlにはrun/cretae/exposeコマンドを利用することで、様々なリソースをYAMLを書かずに作成することができます。
私は次の2点で、kubectl run/create/exposeが素敵だなと思ったので調べた内容を整理します。
・試験時に高速にYAMLを用意してドキュメントを見る回数を減らせる
・勉強時に検証のメインでない部分に時間をかけずに済む
kubectl run
kubectl run XXX
はpodやdeployのリソースをワンライナーで作成することができます。
例えば、image=nginx:alpineを利用したpodを作成する場合は下記のようにします。
$ kubectl run --restart=Never nginx --image=nginx:alpine
pod/nginx created
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 72s
ここまでは多くのドキュメントに書かれていると思うのですが、他にも多くのオプションがあり、それらを有効利用することで効率的なkubectl runライフを送れます。
主要(偏見)なオプションを見てみましょう。
ちなみにKubectl Reference Docsや、kubectl run -h
でも確認できます。
Option | Sample | Description |
---|---|---|
--labels='' -l |
--labels=bu=finance,env=dev -l bu=finance,env=dev |
作成するリソースに付与するラベルを設定します。複数設定する場合は, を利用して繋げます。metadata.labels に該当する設定です。 |
--namespace='' -n |
--namespace=my-ns -n my-ns |
該当リソースをデプロイするnamespaceを指定します。metadata.namespaces. に該当する設定です。 |
--restart='' | --restart=Never | Always, OnFailure, Neverの3種類があります。Alwaysを選択(Default)するとDeploymentリソースが、OnFailureを選択するとJobリソースが、Neverを選択するとPodリソースが作成できます。pod.sepc.restartPolicy に該当する設定です。個人的にはkubectl Usage Conventionsを一読することをお勧めします。 |
--serviceaccount='' | --serviceaccount=my-sa | Service accountを設定します。pod.sepc.serviceAccountName に該当する設定です。 |
--image='' | --image=nginx:alpine | 指定したimageを利用したcontainerをpodに作成します。pod.spec.containers.image に該当する設定です。 |
--env=[] | --env=HOSTNAME=local | Containerで利用する環境変数をNAME=VALUE の形で設定します。ConfigMapやSecretsリソースは使用しません。pod.spec.containers.env に該当する設定です。 |
--port='' | --port=80 | Containerが外部に公開するport番号を指定します。pod.spec.containers.ports.containerPort に該当する設定です。 |
--replicas='' -r |
--replicas=2 -r 2 |
Replica数を指定します。デフォルトでは1が指定されています。deployment.spec.replicas に該当する設定です。 |
--command | --command -- sleep 4800 | Container起動時に実行するコマンドを設定します。Kubernetetsでいうcommand にあたり、Dockerfileでいう、ENTRYPOINT です。 pod.spec.containers.command. に該当する設定です。 |
-- | -- sleep 4800 | Container起動時に引数として渡します。Kubernetetsでいうargs にあたり、Dockerfileでいう、CMD です。 pod.spec.containers.args. に該当する設定です。(2019/10/22追記)
|
--requests='' | --requests='cpu=0.1,memory=10Mi' | Containerのリソース制限を設定できます。pod.spec.containers.resources.limits. に該当する設定です |
--limits='' | --limits='cpu=0.2,memory=20Mi' | Containerのリソース制限を設定できます。pod.spec.containers.resources.limits. に該当する設定です。 |
--schedule='' | --schedule='*/10 * * * *' | 指定したScheduleによるCronJobを作成します。時間設定はcronのルールに乗っとります。cronjob.spec.schedule に該当する設定です。 |
--dry-run | --dry-ryn -o yaml | リソースのデプロイをせずに実行可能かチェックができます。 |
--rm | --rm | 実行後に、コマンドで対象としたリソースを削除します。-itと併用して利用することでトラブルシュートに楽です。 |
Podを作成する(--restart=Never)
例えば、なにかしらのアプリケーションをテストするためにpostgres DBを用意したい時にYAMLから書いていたら面倒です。
下記のような要件とした場合、ワンライナーで作成できます。
・name: my-db
・image: postgres:12-alpine
・env: POSTGRES_PASSWORD=example
・port: 5432
・resources: requests=cpu=0.1,memory=100Mi
limits=cpu=0.2,memory=100Mi
$ kubectl run my-db --restart=Never --image=postgres:12-alpine --port=5432 --env=POSTGRES_PASSWORD=example --namespace=my-ns --requests=`cpu=0.1,memory=50Mi` --limits=`cpu=0.2,memory=100Mi` --dry-run -o yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: my-db
name: my-db
spec:
containers:
- env:
- name: POSTGRES_PASSWORD
value: example
image: postgres:12-alpine
name: my-db
ports:
- containerPort: 5432
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
また個人的に好きなのは--rm
オプションです。
例えばトラブルシュートで疎通性を確認する際に、nslookupやcurlなどを利用したい場合があるかと思います。
その際になにかしらPodを作成するのはいいのですが、テストしたあと削除を忘れたりなど、汚れがちです。
このオプションはそのリソースが完了すると、自動的に削除されるオプションです。
例えばServiceリソースのmy-lbをnslookupしたい時、このような工程が必要です。
$ kubectl run ns --restart=Never --image=busybox:1.28 --command -- nslookup my-lb
pod/ns created
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
my-nginx-6c79cbc966-5kn76 1/1 Running 0 26m
my-nginx-6c79cbc966-jr74c 1/1 Running 0 26m
ns 0/1 Completed 0 5s
$ kubectl logs ns
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
Name: my-lb
Address 1: 10.96.155.99 my-lb.default.svc.cluster.local
$ kubectl delete pod ns
pod "ns" deleted
これを--rm
オプションを利用することで、簡単になります。標準出力のために、-it
オプションも必要です。
$ kubectl run ns --restart=Never --image=busybox:1.28 --rm -it --command -- nslookup my-lb
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
Name: my-lb
Address 1: 10.96.155.99 my-lb.default.svc.cluster.local
pod "ns" deleted
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
my-nginx-6c79cbc966-5kn76 1/1 Running 0 29m
my-nginx-6c79cbc966-jr74c 1/1 Running 0 29m
(2019/10/22追記)
今まで--command
によるENTRYPOINT/ commands
しか作成できないと思っていましたが、CMD / args
も作成できると知ったので追記します。
--
は何気なく書いていますが、これは引数として渡す内容を以降に記載するのですが、これを--command
を書かずに記載します。つまりただの引数として渡すだけなのでCMD / args
になります。
考えればそりゃそうか、、ですが面白かったので共有です。
(ちなみに、引数しか渡していないのでpodの作成は失敗します。pod.spec.containers.command
でENTORYPOINT
としてsleep
を渡してあげれば動きます。)
$ kubectl run --restart=Never busybox --image=busybox --dry-run -o yaml -- 4800
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: busybox
name: busybox
spec:
containers:
- args:
- "4800"
image: busybox
imagePullPolicy: IfNotPresent
name: busybox
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
Deploymentを作成する(--restart=Always)
Deploymentリソースを作成したい場合は次のように作ります。
--restart=Alwaysはデフォルト値なので、記載しなくてもDeploymentリソースとして作成されます。
$ kubectl run my-nginx --restart=Always --image=nginx:alpine --replicas=2 --dry-run -o yaml
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
run: my-nginx
name: my-nginx
spec:
replicas: 2
selector:
matchLabels:
run: my-nginx
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
run: my-nginx
spec:
containers:
- image: nginx:alpine
name: my-nginx
resources: {}
status: {}
Jobを作成する(--restart=OnFailure)
例えば公式ドキュメントのJobsをサンプルに、perlを利用して円周率3.14を出力するJobはこのようにワンライナーで作成できます。
$ kubectl run pi --restart=OnFailure --image=perl --dry-run -o yaml --command -- perl -Mbignum=bpi -wle "print bpi(2000)"
kubectl run --generator=job/v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
apiVersion: batch/v1
kind: Job
metadata:
creationTimestamp: null
labels:
run: pi
name: pi
spec:
template:
metadata:
creationTimestamp: null
labels:
run: pi
spec:
containers:
- command:
- perl
- -Mbignum=bpi
- -wle
- print bpi(2000)
image: perl
name: pi
resources: {}
restartPolicy: OnFailure
status: {}
$ k logs pi-xwjq9
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989380952572010654858632788659361533818279682303019520353018529689957736225994138912497217752834791315155748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035637076601047101819429555961989467678374494482553797747268471040475346462080466842590694912933136770289891521047521620569660240580381501935112533824300355876402474964732639141992726042699227967823547816360093417216412199245863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818347977535663698074265425278625518184175746728909777727938000816470600161452491921732172147723501414419735685481613611573525521334757418494684385233239073941433345477624168625189835694855620992192221842725502542568876717904946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886269456042419652850222106611863067442786220391949450471237137869609563643719172874677646575739624138908658326459958133904780275901
CronJobを作成する(--restart=OnFailure)
先ほど作成したJobをCronJobで作成する例が下記です。CronJobリソース自体は--schedule=''
を利用して作成することができますが、デフォルトではrestart=Always
となるため作成できません。そのため--restart=Never or OnFailure
の設定が必要です。
$ kubectl run pi --image=perl --restart=Never --schedule="*/10 * * * *" --dry-run -o yaml --command -- perl -Mbignum=bpi -wle "print bpi(2000)"
kubectl run --generator=cronjob/v1beta1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
apiVersion: batch/v1beta1
kind: CronJob
metadata:
creationTimestamp: null
labels:
run: pi
name: pi
spec:
concurrencyPolicy: Allow
jobTemplate:
metadata:
creationTimestamp: null
spec:
template:
metadata:
creationTimestamp: null
labels:
run: pi
spec:
containers:
- command:
- perl
- -Mbignum=bpi
- -wle
- print bpi(2000)
image: perl
name: pi
resources: {}
restartPolicy: Never
schedule: '*/10 * * * *'
status: {}
$ kubectl get event | grep cronjob/pi
15m Normal SuccessfulCreate cronjob/pi Created job pi-1569048000
14m Normal SawCompletedJob cronjob/pi Saw completed job: pi-1569048000, status: Complete
5m12s Normal SuccessfulCreate cronjob/pi Created job pi-1569048600
4m51s Normal SawCompletedJob cronjob/pi Saw completed job: pi-1569048600, status: Complete
kubectl expose
kubectl expose XXX
はserviceリソースをワンライナーで作成することができます。
exposeは晒すという意味なので、PODと外部をアクセスするためのリソースと考えるとわかりやすいですね。
主要なオプションを以下にまとめます。
Option | Sample | Description |
---|---|---|
--port='' | --port=80 | Serviceリソースが晒す(expose)するPort番号です。外部からはこのPort番号にアクセスするとServiceリソースが紐づいたリソースにロードバランスされます。 |
--target-port='' | --target-port=80 | ServiceリソースにひもづくContainerが公開しているPort番号を指定します。指定しないと--port で指定した番号を引用します。 |
--type='' | --type=NodePort | 作成するServiceリソースのtypeを指定します。ClusterIP(Default), NodePort, LoadBalancer, ExternalNameが指定できます。 |
--name='' | --name=my-svc | 作成するServiceリソースの名前を指定します。指定しないとexpose対象としたリソースの名前を使用します。 |
--selector=''
オプションを利用することで、Serviceリソースがひもづくリソースを指定できますが、exposeで指定したリソースを自動で参照するため個人的には使う機会は少ないのかと思っています。
ClusterIPを作成する(--type=ClusterIP)
ClusterIPはリソースを作成すると自動で振られます。--cluster-ip=''
を利用することで指定もできますが、意識しないことが寛容です。
下記の例では--type=ClsuterIP
を指定していますが、デフォルト値なので指定は不要です。
$ kubectl expose deploy/my-nginx --type=ClusterIP --port=8080 --target-port=80 --dry-run -o yaml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
run: my-nginx
name: my-nginx
spec:
ports:
- port: 8080
protocol: TCP
targetPort: 80
selector:
run: my-nginx
type: ClusterIP
status:
loadBalancer: {}
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 29d
my-nginx ClusterIP 10.104.190.5 <none> 8080/TCP 87s
NodePortを作成する(--type=NodePort)
NodePortを作成します。ClusterIPとNodePortはリソースを作成すると自動的に振られます。
NodePortは管理せずに自動で振られるものを利用する方が適しているかと思いますが、変更が必要な場合はkubectl edit svc my-np
などでsvc.spec.ports.nodePort
を直接変更すると早いです。
$ kubectl expose deploy/my-nginx --type=NodePort --port=80 --name=my-np --dry-run -o yaml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
run: my-nginx
name: my-np
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
run: my-nginx
type: NodePort
status:
loadBalancer: {}
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 29d
my-nginx ClusterIP 10.104.190.5 <none> 8080/TCP 5m32s
my-np NodePort 10.97.199.41 <none> 80:30541/TCP 72s
LoadBalancerを作成する(--type=LoadBalancer)
ローカルで勉強している際にはあまり使う機会がない(?)と思いますが、今までと同じ手法で作成することができます。外部LBとの連携がないためEXTERNAL-IPはpending stateですが、なにかしら設定したい場合は--external-ip=''
で付与することもできます。
$ kubectl expose deploy/my-nginx --type=LoadBalancer --port=80 --target-port=8888 --name=my-lb --dry-run -o yaml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
run: my-nginx
name: my-lb
spec:
ports:
- port: 80
protocol: TCP
targetPort: 8888
selector:
run: my-nginx
type: LoadBalancer
status:
loadBalancer: {}
$ kg svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 29d
my-lb LoadBalancer 10.96.155.99 <pending> 80:31957/TCP 20s
my-nginx ClusterIP 10.104.190.5 <none> 8080/TCP 10m
my-np NodePort 10.97.199.41 <none> 80:30541/TCP 6m1s
kubectl create
kubectl create XXX
は多くのリソースをワンライナーで作成することができます。表現できないYAMLがあっても出力結果を少しいじれば多くのケースで対応でき、とても便利です。
$ kubectl create -h | grep Ava -A 15
Available Commands:
clusterrole Create a ClusterRole.
clusterrolebinding Create a ClusterRoleBinding for a particular ClusterRole
configmap Create a configmap from a local file, directory or literal value
cronjob Create a cronjob with the specified name.
deployment Create a deployment with the specified name.
job Create a job with the specified name.
namespace Create a namespace with the specified name
poddisruptionbudget Create a pod disruption budget with the specified name.
priorityclass Create a priorityclass with the specified name.
quota Create a quota with the specified name.
role Create a role with single rule.
rolebinding Create a RoleBinding for a particular Role or ClusterRole
secret Create a secret using specified subcommand
service Create a service using specified subcommand.
serviceaccount Create a service account with the specified name
deployment, job, cronjob, serviceなどkubectl run/exposeで作成できたものもkubectl createから作成できますが、オプションが少なく実用的ではないかと思います。
namespaceを作成する
namespaceは以下のように作成します。
$ kubectl create ns test
namespace/test created
$ kubectl get ns test
NAME STATUS AGE
test Active 11s
ConfigMap, Secretを作成する
ConfigMapは環境変数を以下の方法で読み込めます。
Option | Sample | Description |
---|---|---|
--from-env-file='' | --from-env-file=test.env | key=valueで記載された環境変数ファイルを読み込みます。 |
--from-file='' | --from-file=path/dir/, --from-file=env.txt, --from-file=key1=env.txt | ファイル名をkey、もしくはkeyを指定してvalueとしてファイルを読み込みます。 |
--from-literal='' | --from-literal=key1=value1 --from-literal=key2=value2 | コマンド上で読み込む環境変数を設定します。複数設定したい場合は--from-literal を環境変数のkey=valueの1セットで追加していく必要があります。 |
この中でも事前にファイルを用意する必要がないので--from-literal=''
は非常に便利なコマンドです。
$ kubectl create cm test-cm --from-literal=key1=value1 --from-literal=key2=value2 --dry-run -o yaml
apiVersion: v1
data:
key1: value1
key2: value2
kind: ConfigMap
metadata:
creationTimestamp: null
name: test-cm
Secretの場合は作成する内容によってdocker-registry
、generic
、tls
の選択は必要ですが、考え方はConfigMapと同じです。
また、base64 encodingを地震でする必要がないので楽です。
$ kubectl create secret generic test-secret --from-literal=key1=value1 --from-literal=key2=value2 --dry-run -o yaml
apiVersion: v1
data:
key1: dmFsdWUx
key2: dmFsdWUy
kind: Secret
metadata:
creationTimestamp: null
name: test-secret
$ echo "dmFsdWUx" | base64 -d
value1
ServiceAccount, role(clusterrole), rolebinding(clusterrolebinding)を作成する
権限関連です。これらは作成するリソースが多いので、YAMLファイルのテンプレートを引っ張ってくるのは手間がかかります。
しかしkubectl createではワンライナーでほとんどを作成することができます。
例えばjohnというserviceaccountにwatcherというroleを付与したい場合は3コマンドで済みます。
$ kubectl create sa john
serviceaccount/john created
$ kubectl create role watcher --verb=get,list,watch --resource=pod,deploy
role.rbac.authorization.k8s.io/watcher created
$ kubectl create rolebinding john-watcherer --role=watch --serviceaccount=test:john
rolebinding.rbac.authorization.k8s.io/john-watcherer created
$ kubectl auth can-i list pod --as system:serviceaccount:test:john
yes
$ kubectl auth can-i list pod --as system:serviceaccount:default:john
no
$ kubectl auth can-i create pod --as system:serviceaccount:test:john
no
$ kubectl auth can-i watch deploy --as system:serviceaccount:test:john
yes
これをYAMLで実現しようとすると非常に手間がかかります。
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: null
name: john
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
creationTimestamp: null
name: watcher
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- list
- watch
- apiGroups:
- extensions
resources:
- deployments
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
creationTimestamp: null
name: john-watcher
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: watcher
subjects:
- kind: ServiceAccount
name: john
namespace: test
まとめ
結構長くなりましたが、ぜひ勉強を始めたばかりの方に共有したいと思いまとめました。
間違いなどあれば指摘もらえると嬉しいです。
ありがとうございました。