kubernetes 学習 ExternalIP
クラスタ外から指定したNodeIPを通してpodへアクセスできるようにする。 指定したip の node がダウンしている場合は疎通できない。nodeportも同様
kbhello-service-eip.yaml
apiVersion: v1 kind: Service metadata: name: kbhello-service-eip spec: selector: app: kbhello type: ClusterIP externalIPs: - 192.168.0.101 ports: - port: 8080
$ kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES kbhello-deployment-664dd576d4-29pkt 1/1 Running 0 5d 10.244.1.90 kb2 <none> <none> kbhello-deployment-664dd576d4-l64ft 1/1 Running 0 14s 10.244.2.39 kb3 <none> <none> kbhello-deployment-664dd576d4-zztrq 1/1 Running 0 14s 10.244.2.38 kb3 <none> <none>
$ curl 192.168.0.101:8080 Hello Docker World kbhello-deployment-664dd576d4-zztrq Hello Docker World kbhello-deployment-664dd576d4-29pkt Hello Docker World kbhello-deployment-664dd576d4-l64ft
kubernetes 学習 NodePort
前回は、クラスタ内部間の通信を調べた。 クラスタ外部 -> サービス -> pod の経路を調べたい。
確認
kb2 に pod:29pkt, pod:nrj9j。kb3 に pod:n9t8t。
$ kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES kbhello-deployment-664dd576d4-29pkt 1/1 Running 0 24h 10.244.1.90 kb2 <none> <none> kbhello-deployment-664dd576d4-n9t8t 1/1 Running 0 24h 10.244.2.37 kb3 <none> <none> kbhello-deployment-664dd576d4-nrj9j 1/1 Running 0 24h 10.244.1.91 kb2 <none> <none>
EXTERNAL-IP にip設定すればいいのかな?
$ kubectl get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kbhello-service-cip ClusterIP 10.104.228.167 <none> 8080/TCP 3d22h kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 43d
LoadBalancer を試す
apiVersion: v1 kind: Service metadata: name: kbhello-service-lb spec: selector: app: kbhello type: LoadBalancer ports: - port: 8080 loadBalancerIP: 192.168.0.111
やっぱり失敗。EXTERNAL-IP:pending。LoadBalancer にipを渡す人が必要なのか。
$ kubectl get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kbhello-service-cip ClusterIP 10.104.228.167 <none> 8080/TCP 3d23h kbhello-service-lb LoadBalancer 10.111.236.45 <pending> 8080:30202/TCP 97s kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 43d
CLUSTER-IP のcurl はOK
$ curl 10.111.236.45:8080 Hello Docker World kbhello-deployment-664dd576d4-n9t8t Hello Docker World kbhello-deployment-664dd576d4-29pkt Hello Docker World kbhello-deployment-664dd576d4-nrj9j
NodePort を試す
NodePort。ノードポート。node内のpodには行けても、別nodeのpodには行けない感。
NodePortは、全てのKubernetes NodeのIP:Portで受けたトラフィックをコンテナに転送する形で、外部疎通性を確立します。 https://thinkit.co.jp/article/13738?page=0%2C1
NodePortは各NodeのIPでポートを公開します。これにより、クラスタの外からServiceにアクセスできるようになります。 https://codezine.jp/article/detail/10523
試してみる。
$ kubectl expose deployment kbhello-deployment --type=NodePort --port 8080 service/kbhello-deployment exposed $ kubectl get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kbhello-deployment NodePort 10.110.104.66 <none> 8080:30199/TCP 18s kbhello-service-cip ClusterIP 10.104.228.167 <none> 8080/TCP 3d23h kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 44d
node:kb2 にcurl。node3のレスポンスもあった。
$ curl 192.168.0.102:8080 curl: (7) Failed to connect to 192.168.0.102 port 8080: Connection refused $ curl 192.168.0.102:30199 Hello Docker World kbhello-deployment-664dd576d4-29pkt Hello Docker World kbhello-deployment-664dd576d4-nrj9j Hello Docker World kbhello-deployment-664dd576d4-29pkt Hello Docker World kbhello-deployment-664dd576d4-n9t8t <--- node:kb3 Hello Docker World kbhello-deployment-664dd576d4-nrj9j
node:kb3 にcurl。node2のレスポンスもあった。
$ curl 192.168.0.103:8080 curl: (7) Failed to connect to 192.168.0.103 port 8080: Connection refused $ curl 192.168.0.103:30199 Hello Docker World kbhello-deployment-664dd576d4-n9t8t Hello Docker World kbhello-deployment-664dd576d4-29pkt <--- node:kb2 Hello Docker World kbhello-deployment-664dd576d4-29pkt <--- node:kb2 Hello Docker World kbhello-deployment-664dd576d4-29pkt <--- node:kb2 Hello Docker World kbhello-deployment-664dd576d4-nrj9j <--- node:kb2
pod を1個にしてcurl してみる。
podがないnodeを作ったらどうなる?
$ kubectl edit deployment kbhello-deployment : replicas: 3 ↓ replicas: 1
node:kb2 だけになったことを確認。
$ kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES kbhello-deployment-664dd576d4-29pkt 1/1 Running 0 24h 10.244.1.90 kb2 <none> <none>
curl。podがない kb3(103) の port からもレスポンスがある。なるほど、欲しかったのはNodePortだったのか。
core@kb1 ~ $ curl 192.168.0.102:30199 Hello Docker World kbhello-deployment-664dd576d4-29pkt core@kb1 ~ $ curl 192.168.0.103:30199 Hello Docker World kbhello-deployment-664dd576d4-29pkt
NodePortだと別nodeのpodには行けない、は勘違いでした。
NodePortを指定する
さっきのやり方ではNodePort の番号を指定できないようなのでマニフェストにしてみた。
kbhello-service-np.yaml
apiVersion: v1 kind: Service metadata: name: kbhello-service-np spec: selector: app: kbhello type: NodePort ports: - port: 8080 nodePort: 30080
マニフェスト適用。
$ kubectl apply -f kbhello-service-np.yaml service/kbhello-service-np created $ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kbhello-deployment NodePort 10.110.104.66 <none> 8080:30199/TCP 28m kbhello-service-cip ClusterIP 10.104.228.167 <none> 8080/TCP 4d kbhello-service-np NodePort 10.99.42.155 <none> 8080:30080/TCP 8s kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 44d
curlで確認。podが1コしかないけど想定通りの結果が得られた。
$ curl 192.168.0.102:30080 Hello Docker World kbhello-deployment-664dd576d4-29pkt Hello Docker World kbhello-deployment-664dd576d4-29pkt $ curl 192.168.0.103:30080 Hello Docker World kbhello-deployment-664dd576d4-29pkt Hello Docker World kbhello-deployment-664dd576d4-29pkt
kubernetes 学習 dns
service, pod の名前解決を調べた。
最初に確認
kbhello でHOSTNAMEを表示するようにした。 kbhello-deployment が 3podあり、kb2 kb3 の2node で実行中。
$ kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES kbhello-deployment-664dd576d4-29pkt 1/1 Running 0 15m 10.244.1.90 kb2 <none> <none> kbhello-deployment-664dd576d4-n9t8t 1/1 Running 0 33s 10.244.2.37 kb3 <none> <none> kbhello-deployment-664dd576d4-nrj9j 1/1 Running 0 15m 10.244.1.91 kb2 <none> <none>
ClusterIP 確認
$ kubectl get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kbhello-service-cip ClusterIP 10.104.228.167 <none> 8080/TCP 2d23h kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 42d
curl。ip:10.104.228.167 が3pod(2node) に対応していることが分かる。
$ curl 10.104.228.167:8080 Hello Docker World kbhello-deployment-664dd576d4-n9t8t $ curl 10.104.228.167:8080 Hello Docker World kbhello-deployment-664dd576d4-nrj9j $ curl 10.104.228.167:8080 Hello Docker World kbhello-deployment-664dd576d4-29pkt
ClusterIPの名前解決
kbhello がクラスタ内のapiサービスだとしたら、このapiにどうやってアクセスしたらいい? ipアドレスはサービス作成毎に変わってしまうから名前で引きたい。
「通常の」(ヘッドレスではない)サービスには、フォームの名前のDNS Aレコードが割り当てられています。 「my-svc.my-namespace.svc.cluster.local」 これはサービスのクラスタIPに解決されます。
ということは、こうなる。
kbhello-service-cip.default.svc.cluster.local
pod から ping してみる。なるほど。
$ kubectl exec -it kbhello-deployment-664dd576d4-n9t8t ping kbhello-service-cip.default.svc.cluster.local PING kbhello-service-cip.default.svc.cluster.local (10.104.228.167): 56 data bytes ^C --- kbhello-service-cip.default.svc.cluster.local ping statistics --- 3 packets transmitted, 0 packets received, 100% packet loss command terminated with exit code 1 $ kubectl exec -it kbhello-deployment-664dd576d4-nrj9j ping kbhello-service-cip.default.svc.cluster.local PING kbhello-service-cip.default.svc.cluster.local (10.104.228.167): 56 data bytes : $ kubectl exec -it kbhello-deployment-664dd576d4-29pkt ping kbhello-service-cip.default.svc.cluster.local PING kbhello-service-cip.default.svc.cluster.local (10.104.228.167): 56 data bytes :
名前解決はしているが、レシーブせず100%ロスしている。 nslookup してみた。
$ kubectl exec -it kbhello-deployment-664dd576d4-29pkt nslookup kbhello-service-cip.default.svc.cluster.local nslookup: can't resolve '(null)': Name does not resolve Name: kbhello-service-cip.default.svc.cluster.local Address 1: 10.104.228.167 kbhello-service-cip.default.svc.cluster.local
/etc/resolv.conf を確認。
$ kubectl exec -it kbhello-deployment-664dd576d4-29pkt cat /etc/resolv.conf nameserver 10.96.0.10 search default.svc.cluster.local svc.cluster.local cluster.local options ndots:5
完全修飾でなく サービス名:kbhello-service-cip でも引けそうだ。引けた。
$ kubectl exec -it kbhello-deployment-664dd576d4-29pkt nslookup kbhello-service-cip core@kb1 ~ $ kubectl exec -it kbhello-deployment-664dd576d4-29pkt nslookup kbhello-service-cip nslookup: can't resolve '(null)': Name does not resolve Name: kbhello-service-cip Address 1: 10.104.228.167 kbhello-service-cip.default.svc.cluster.local
逆に完全修飾ならnamepsaceを超えられるのか?
/etc/hosts を確認。10.244.1.90 はこのpod のipアドレス。kbhello-deployment-664dd576d4-29pkt はこのポッドの名前。
$ kubectl exec -it kbhello-deployment-664dd576d4-29pkt cat /etc/hosts # Kubernetes-managed hosts file. 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet fe00::0 ip6-mcastprefix fe00::1 ip6-allnodes fe00::2 ip6-allrouters 10.244.1.90 kbhello-deployment-664dd576d4-29pkt
Podの名前解決
podも名前解決できるようだ。
ポッドにはDNS Aレコードが「pod-ip-address.my-namespace.pod.cluster.local」の形式で割り当てられます。
ということは、こうか。
10-244-1-90.default.pod.cluster.local 10-244-2-37.default.pod.cluster.local 10-244-1-91.default.pod.cluster.local
ping してみる。こちらはレシーブしている。
$ kubectl exec -it kbhello-deployment-664dd576d4-29pkt ping 10-244-1-90.default.pod.cluster.local PING 10-244-1-90.default.pod.cluster.local (10.244.1.90): 56 data bytes 64 bytes from 10.244.1.90: seq=0 ttl=64 time=0.048 ms : $ kubectl exec -it kbhello-deployment-664dd576d4-29pkt ping 10-244-1-91.default.pod.cluster.local PING 10-244-1-91.default.pod.cluster.local (10.244.1.91): 56 data bytes 64 bytes from 10.244.1.91: seq=0 ttl=63 time=0.116 ms : $ kubectl exec -it kbhello-deployment-664dd576d4-29pkt ping 10-244-2-37.default.pod.cluster.local PING 10-244-2-37.default.pod.cluster.local (10.244.2.37): 56 data bytes 64 bytes from 10.244.2.37: seq=0 ttl=62 time=0.575 ms :
podの名前解決が必要なケースはなんだろう。思いつかない。
kubernetes 学習 service/ClusterIP
これまなんとなく雰囲気でサービス・ロードバランサを作っていた。serviceはたぶん pod/deployment の前段にあたる概念だよなーと考えていた。
Serviceとは?
K8sのサービスは、論理的なPodのセットとそれと通信するためのポリシーを定義する抽象的なものです。これはマイクロサービスと呼ばれることもあります。 サービスを介して通信する一連のポッドは、通常、ラベル・セレクタによって決定されます。
https://kubernetes.io/docs/concepts/services-networking/service/ https://qiita.com/kouares/items/94a073baed9dffe86ea0
なるほど、大体間違っていなかったようだ。そして「ラベル・セレクタ」などによってターゲットpodsを指定すると。
雰囲気で作っていた
いままで、なんとなくこんな感じでロードバランサを作成していた。
kubectl expose deployment kbhello-deployment --type=LoadBalancer --name=kbhello-service
残骸serviceが残っていたので yaml を確認してみる。
$ kubectl get service kbhello-service -o yaml apiVersion: v1 kind: Service metadata: creationTimestamp: "2019-03-04T12:14:50Z" name: kbhello-service namespace: default resourceVersion: "2306882" selfLink: /api/v1/namespaces/default/services/kbhello-service uid: 1c5a9ac4-3e77-11e9-8f5d-9ca3ba319985 spec: clusterIP: 10.98.159.32 externalTrafficPolicy: Cluster ports: - nodePort: 31872 port: 8080 protocol: TCP targetPort: 8080 selector: app: kbhello sessionAffinity: None type: LoadBalancer status: loadBalancer: {}
お掃除
kubectl get all
で k8s の ClusterIP しかない状態にする。そう、この ClusterIP ってなんだろとは思っていた。
$ kubectl delete service quarkusstarted-service service "quarkusstarted-service" deleted $ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 40d $ kubectl get all NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 40d
続けてテキトーなdeployment作成。
$ kubectl apply -f kbhello-deployment.yaml deployment.apps/kbhello-deployment created $ kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES kbhello-deployment-7cd47cbb58-4dlk8 1/1 Running 0 84s 10.244.1.89 kb2 <none> <none> kbhello-deployment-7cd47cbb58-jxjsx 1/1 Running 0 84s 10.244.1.88 kb2 <none> <none> $ curl 10.244.1.89:8080 Hello Docker World $ curl 10.244.1.88:8080 Hello Docker World
ClusterIP 作成
Service にはいくつか種類があるが、ClusterIP を作ってみる。
selector=app:kbhello
って感じか。
kbhello-service-cip.yaml
apiVersion: v1 kind: Service metadata: name: kbhello-service-cip spec: selector: app: kbhello type: ClusterIP ports: - port: 8080
apply して get。表示されたip にcurl。なるほど。クラスタ内通信ならLoadBalancerでなく、外部ipが不要なClusterIPで十分ってことか。LoadBalancer の EXTERNAL-IPが pending になっていたのはipが取得できなかったのだ。
$ kubectl apply -f kbhello-service-cip.yaml service/kbhello-service-cip created $ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kbhello-service-cip ClusterIP 10.104.228.167 <none> 8080/TCP 6s kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 40d $ curl 10.104.228.167:8080 Hello Docker World
Quarkus - Creating Your First Application
java コンテナイメージのサイズに悩んでいたところ、こんなニュースがあった。 高速起動にはあまり興味がないが、Quarkus のイメージサイズに興味を覚えた。
- Javaフレームワーク「Quarkus」登場。Javaコードからネイティブバイナリを生成し瞬時にJavaアプリが起動、コンテナへの最適化を実現。Red Hatがリリース
- Quarkus: コンテナ上で Java アプリを高速起動する新しい手法のご紹介
- Quarkus
Quarkus ってなに?
https://yoshio3.com/2019/03/11/try-quarkus/ より
Quarkus を簡単にご説明すると、Java のソースコードを GraalVM を利用して Linux の Native バイナリを作成し、その Linux バイナリをコンテナ上で起動することにより、今まで Java アプリの課題であった起動時間を大幅に短縮することができる技術です。
GraalVM ってなに?
https://www.graalvm.org/ google翻訳
GraalVMは、JavaScript、Python、Ruby、R、Java、Scala、Kotlin、ClojureなどのJVMベースの言語、およびCやC ++などのLLVMベースの言語で作成されたアプリケーションを実行するための汎用仮想マシンです。
graalvm いれる
- https://www.graalvm.org/downloads/
- wget
- tar xvf
- mv graalvm-ce-1.0.0-rc13 /opt
- export PATH=/opt/graalvm-ce-1.0.0-rc13/bin:$PATH
- java -version
openjdk version "1.8.0_202" OpenJDK Runtime Environment (build 1.8.0_202-20190206132807.buildslave.jdk8u-src-tar--b08) OpenJDK GraalVM CE 1.0.0-rc13 (build 25.202-b08-jvmci-0.55, mixed mode)
Quarkus - Creating Your First Application
チュートリアル 通りにやってみる。
getting-started ディレクトリ下にプロジェクトが生成される。
mvn io.quarkus:quarkus-maven-plugin:0.11.0:create \ -DprojectGroupId=jp.acme \ -DprojectArtifactId=getting-started \ -DclassName="org.acme.quickstart.GreetingResource" \ -Dpath="/hello"
アプリケーション起動(devモード)
$ cd ./getting-started $ mvn compile quarkus:dev
アプリケーション確認
$ curl http://localhost:8080 > Congratulations, you have created a new Quarkus application. > とかなんとか $ curl http://localhost:8080/hello hello
- Using injection
今度試す
なるほどいいね。次も今度試す。
- Testing
- Packaging and run the application
- Async
docker してみる
src/main/docker/Dockerfile を確認。イメージ生成手順が載っています。 target/*-runner
を実行することが分かる。
#### # Before building the docker image run: # # mvn package -Pnative -Dnative-image.docker-build=true # # Then, build the image with: # # docker build -f src/main/docker/Dockerfile -t quarkus/getting-started . # # Then run the container using: # # docker run -i --rm -p 8080:8080 quarkus/getting-started # ### FROM registry.fedoraproject.org/fedora-minimal WORKDIR /work/ COPY target/*-runner /work/application RUN chmod 775 /work EXPOSE 8080 CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
target ディレクトリも見てみる。 target/*-runner
は20MB
$ ls -alh target 合計 20M drwxrwxr-x 14 tjtjtj tjtjtj 4.0K 3月 18 20:50 . drwxrwxr-x 4 tjtjtj tjtjtj 4.0K 3月 18 22:50 .. drwxrwxr-x 4 tjtjtj tjtjtj 4.0K 3月 18 19:59 classes drwxrwxr-x 3 tjtjtj tjtjtj 4.0K 3月 18 19:39 generated-sources drwxrwxr-x 3 tjtjtj tjtjtj 4.0K 3月 18 19:59 generated-test-sources -rwxr-xr-x 1 root root 20M 3月 18 20:50 getting-started-1.0-SNAPSHOT-runner -rw-r--r-- 1 root root 36K 3月 18 20:04 getting-started-1.0-SNAPSHOT-runner.jar -rw-rw-r-- 1 tjtjtj tjtjtj 5.3K 3月 18 20:04 getting-started-1.0-SNAPSHOT.jar drwxrwxr-x 2 tjtjtj tjtjtj 4.0K 3月 18 20:04 lib drwxrwxr-x 2 tjtjtj tjtjtj 4.0K 3月 18 19:59 maven-archiver drwxrwxr-x 3 tjtjtj tjtjtj 4.0K 3月 18 19:39 maven-status -rw-rw-r-- 1 tjtjtj tjtjtj 3.5K 3月 18 20:04 quarkus.log drwxr-xr-x 2 root root 4.0K 3月 18 20:33 reports drwxrwxr-x 2 tjtjtj tjtjtj 4.0K 3月 18 19:59 surefire-reports drwxrwxr-x 6 tjtjtj tjtjtj 4.0K 3月 18 19:59 test-classes drwxrwxr-x 2 tjtjtj tjtjtj 4.0K 3月 18 19:59 transformed-classes drwxrwxr-x 6 tjtjtj tjtjtj 4.0K 3月 18 19:59 wiring-classes drwxrwxr-x 4 tjtjtj tjtjtj 4.0K 3月 18 19:39 wiring-devmode
ネイティブバイナリ生成。これが噂のlinuxに最適化されたバイナリ生成か。しっかし時間かかったね。ショボvm のせいもあり参考になさらず。
# mvn package -Pnative -Dnative-image.docker-build=true : [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 48:16 min [INFO] Finished at: 2019-03-18T20:50:50+09:00 [INFO] ------------------------------------------------------------------------
イメージサイズ。125MBか。openjdk:8-jdk-alpine の121MB とあまり変わらないサイズ。
# docker images REPOSITORY TAG IMAGE ID CREATED SIZE quarkus/getting-started latest 2bde28a5057f About a minute ago 125MB
docker build
# docker build -f src/main/docker/Dockerfile -t quarkus/getting-started .
docker run。確かに一瞬で起動する。バイナリ生成時間をとるか、起動時間をとるか。
# docker run -i --rm -p 8080:8080 quarkus/getting-started
動作確認
$ curl http://localhost:8080/hello hello
kubernetes してみる
タギング, docker-login, タグpush
docker tag quarkus/getting-started:latest 192.168.0.1:5000/quarkus/getting-started:latest docker login 192.168.0.1:5000 docker push 192.168.0.1:5000/quarkus/getting-started:latest
イメージ確認
# docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE 192.168.0.1:5000/quarkus/getting-started latest 2bde28a5057f About an hour ago 125MB quarkus/getting-started latest 2bde28a5057f About an hour ago 125MB
カタログ確認
# curl localhost:5000/v2/_catalog {"repositories":["kbhello","quarkus/getting-started"]}
quarkusstarted-deployment.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: quarkusstarted-deployment spec: replicas: 2 selector: matchLabels: app: quarkusstarted template: metadata: labels: app: quarkusstarted spec: containers: - name: quarkusstarted image: 192.168.0.1:5000/quarkus/getting-started ports: - containerPort: 8080
デプロイ
$ kubectl apply -f quarkusstarted-deployment.yaml deployment.apps/quarkusstarted-deployment created $ kubectl get pod NAME READY STATUS RESTARTS AGE quarkusstarted-deployment-7896c77d8c-h7k4n 1/1 Running 0 19s quarkusstarted-deployment-7896c77d8c-vh42p 1/1 Running 0 19s
ロードバランサ作成
$ kubectl expose deployment quarkusstarted-deployment --type=LoadBalancer --name=quarkusstarted-service service/quarkusstarted-service exposed $ kubectl get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 33d quarkusstarted-service LoadBalancer 10.103.221.38 <pending> 8080:30423 /TCP 14s
確認
$ curl http://10.103.221.38:8080/hello hello
kubernetes 学習 logging その1
Logging Architecture を試す。
- コンテナ化されたアプリケーションの最も簡単で包括的なロギング方法は、標準出力と標準エラーストリームに書き込むこと
- クラスタレベルのログ記録では、ログを保存、分析、およびクエリするために別のバックエンドが必要
- Kubernetesはログデータ用のネイティブストレージソリューションを提供しない
- Kubernetesクラスタに既存のロギングソリューションを多数統合できる
Kubernetesでの基本的なログ記録
1秒に1回テキストを標準出力するポッド
debug/counter-pod.yaml
apiVersion: v1 kind: Pod metadata: name: counter spec: containers: - name: count image: busybox args: [/bin/sh, -c, 'i=0; while true; do echo "$i: $(date)"; i=$((i+1)); sleep 1; done']
$ kubectl apply -f debug/counter-pod.yaml pod/counter created $ kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES counter 1/1 Running 0 14s 10.244.1.84 kb2 <none> <none> $ kubectl describe pod counter Name: counter Namespace: default Priority: 0 PriorityClassName: <none> Node: kb2/192.168.0.102 Start Time: Mon, 11 Mar 2019 19:44:53 +0900 Labels: <none> Annotations: cni.projectcalico.org/podIP: 10.244.1.84/32 kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"name":"counter","namespace":"default"},"spec":{"containers":[{"args":["/bin/... Status: Running IP: 10.244.1.84 Containers: count: Container ID: docker://5e5c7d509ce1bfadac97749fb855f5771042fce001972efb7b1874cf769fbb2f Image: busybox Image ID: docker-pullable://busybox@sha256:061ca9704a714ee3e8b80523ec720c64f6209ad3f97c0ff7cb9ec7d19f15149f Port: <none> Host Port: <none> Args: /bin/sh -c i=0; while true; do echo "$i: $(date)"; i=$((i+1)); sleep 1; done
pod:counter のログを確認
$ kubectl log counter log is DEPRECATED and will be removed in a future version. Use logs instead. 0: Mon Mar 11 10:44:59 UTC 2019 1: Mon Mar 11 10:45:00 UTC 2019 2: Mon Mar 11 10:45:01 UTC 2019 3: Mon Mar 11 10:45:02 UTC 2019 4: Mon Mar 11 10:45:03 UTC 2019 5: Mon Mar 11 10:45:04 UTC 2019 6: Mon Mar 11 10:45:05 UTC 2019 7: Mon Mar 11 10:45:06 UTC 2019 8: Mon Mar 11 10:45:07 UTC 2019 9: Mon Mar 11 10:45:08 UTC 2019 10: Mon Mar 11 10:45:09 UTC 2019 :
ノード上のログを確認してみる
kb2 の /var/log/containers を確認。counter_default_count-5e5c7d50... を追跡する。/var/log/pods/b460364c-43ea-11e9-8f5d-9ca3ba319985/count/0.log. にリンクしている
$ ls -al /var/log/containers total 80 drwxr-xr-x. 2 root root 12288 Mar 11 19:44 . drwxr-xr-x. 7 root root 4096 Jan 25 20:38 .. lrwxrwxrwx. 1 root root 68 Feb 28 23:58 calico-node-jdbbb_kube-system_calico-node-44f1f3e3277039d626404d7f4f4f9bdb97349b762ba38ce6e4fac50cf21a1c2b.log -> /var/log/pods/a206ccdc-2f85-11e9-83f4-9ca3ba319985/calico-node/3.log lrwxrwxrwx. 1 root root 68 Feb 24 16:03 calico-node-jdbbb_kube-system_calico-node-80765d945664af23866537c55b7dcfead8a0ce3e8e9649494621f35104fd44c9.log -> /var/log/pods/a206ccdc-2f85-11e9-83f4-9ca3ba319985/calico-node/2.log lrwxrwxrwx. 1 root root 68 Feb 24 16:03 calico-node-jdbbb_kube-system_install-cni-3c4e153bae5aa417322473e704275c3ec5a2e541a4fdafa022e2d92009183bfe.log -> /var/log/pods/a206ccdc-2f85-11e9-83f4-9ca3ba319985/install-cni/2.log lrwxrwxrwx. 1 root root 68 Feb 28 23:58 calico-node-jdbbb_kube-system_install-cni-4799ede6da39807478b6316ce18957d255575132d620d524a06b6e98566e8948.log -> /var/log/pods/a206ccdc-2f85-11e9-83f4-9ca3ba319985/install-cni/3.log lrwxrwxrwx. 1 root root 62 Mar 11 19:44 counter_default_count-5e5c7d509ce1bfadac97749fb855f5771042fce001972efb7b1874cf769fbb2f.log -> /var/log/pods/b460364c-43ea-11e9-8f5d-9ca3ba319985/count/0.log lrwxrwxrwx. 1 root root 67 Feb 28 23:58 kube-proxy-x6gbc_kube-system_kube-proxy-2acc29cfc69b74874faa11d4c9a793a7a43b9925575c112a4015f7af39ee09c8.log -> /var/log/pods/a204dab0-2f85-11e9-83f4-9ca3ba319985/kube-proxy/4.log lrwxrwxrwx. 1 root root 67 Feb 24 16:03 kube-proxy-x6gbc_kube-system_kube-proxy-942c1bd44c48442bfe17c9add49cbad796ac224f00fb89b2e2eabe834739de05.log -> /var/log/pods/a204dab0-2f85-11e9-83f4-9ca3ba319985/kube-proxy/3.log
/var/log/pods には b460364c-43ea-11e9-8f5d-9ca3ba319985 があって...
$ ls -al /var/log/pods total 40 drwxr-xr-x. 5 root root 4096 Mar 11 19:44 . drwxr-xr-x. 7 root root 4096 Jan 25 20:38 .. drwxr-xr-x. 3 root root 4096 Feb 13 20:51 a204dab0-2f85-11e9-83f4-9ca3ba319985 drwxr-xr-x. 4 root root 4096 Feb 13 20:51 a206ccdc-2f85-11e9-83f4-9ca3ba319985 drwxr-xr-x. 3 root root 4096 Mar 11 19:44 b460364c-43ea-11e9-8f5d-9ca3ba319985
/var/log/pods/b460364c-.../ には count があって...
$ ls -al /var/log/pods/b460364c-43ea-11e9-8f5d-9ca3ba319985 total 24 drwxr-xr-x. 3 root root 4096 Mar 11 19:44 . drwxr-xr-x. 5 root root 4096 Mar 11 19:44 .. drwxr-xr-x. 2 root root 4096 Mar 11 19:44 count
/var/log/pods/b460364c-.../count/ には 0.log があって /var/lib/docker/containers/5e5c7d5.../5e5c7d5...-json.log にリンクしている
$ ls -al /var/log/pods/b460364c-43ea-11e9-8f5d-9ca3ba319985/count total 24 drwxr-xr-x. 2 root root 4096 Mar 11 19:44 . drwxr-xr-x. 3 root root 4096 Mar 11 19:44 .. lrwxrwxrwx. 1 root root 165 Mar 11 19:44 0.log -> /var/lib/docker/containers/5e5c7d509ce1bfadac97749fb855f5771042fce001972efb7b1874cf769fbb2f/5e5c7d509ce1bfadac97749fb855f5771042fce001972efb7b1874cf769fbb2f-json.log
/var/lib/docker/containers/5e5c7d5.../5e5c7d5...-json.log の内容を確認。json で log フィールドに記録されていた。
$ sudo tail /var/lib/docker/containers/5e5c7d509ce1bfadac97749fb855f5771042fce001972efb7b1874cf769fbb2f/5e5c7d509ce1bfadac97749fb855f5771042fce001972efb7b1874cf769fbb2f-json.log {"log":"707: Mon Mar 11 10:56:47 UTC 2019\n","stream":"stdout","time":"2019-03-11T10:56:47.219187708Z"} {"log":"708: Mon Mar 11 10:56:48 UTC 2019\n","stream":"stdout","time":"2019-03-11T10:56:48.220973929Z"} {"log":"709: Mon Mar 11 10:56:49 UTC 2019\n","stream":"stdout","time":"2019-03-11T10:56:49.222537805Z"} {"log":"710: Mon Mar 11 10:56:50 UTC 2019\n","stream":"stdout","time":"2019-03-11T10:56:50.223903951Z"} {"log":"711: Mon Mar 11 10:56:51 UTC 2019\n","stream":"stdout","time":"2019-03-11T10:56:51.225434989Z"} {"log":"712: Mon Mar 11 10:56:52 UTC 2019\n","stream":"stdout","time":"2019-03-11T10:56:52.226873482Z"} {"log":"713: Mon Mar 11 10:56:53 UTC 2019\n","stream":"stdout","time":"2019-03-11T10:56:53.22864989Z"} {"log":"714: Mon Mar 11 10:56:54 UTC 2019\n","stream":"stdout","time":"2019-03-11T10:56:54.230080744Z"} {"log":"715: Mon Mar 11 10:56:55 UTC 2019\n","stream":"stdout","time":"2019-03-11T10:56:55.231569155Z"} {"log":"716: Mon Mar 11 10:56:56 UTC 2019\n","stream":"stdout","time":"2019-03-11T10:56:56.233325322Z"}
springboot+docker イメージのサイズ縮小
前回の続き。イメージのサイズの縮小を試す。今回は MultiStageBuild の必要性が理解できている。
hirokimatsumoto/alpine-openjdk-11 + alpine:3.8
ここ を参考にした。
イメージサイズ: 78.7MB。これは小さい。
Dockerfile.hiroki
FROM hirokimatsumoto/alpine-openjdk-11:latest as jlink-package # First: generate java runtime module by jlink. RUN jlink \ --module-path /opt/java/jmods \ --compress=2 \ --add-modules jdk.jfr,jdk.management.agent,java.base,java.logging,java.xml,jdk.unsupported,java.sql,java.naming,java.desktop,java.management,java.security.jgss,java.instrument \ --no-header-files \ --no-man-pages \ --output /opt/jdk-11-mini-runtime # Second: generate run image. FROM alpine:3.8 ENV JAVA_HOME=/opt/jdk-11-mini-runtime ENV PATH="$PATH:$JAVA_HOME/bin" COPY --from=jlink-package /opt/jdk-11-mini-runtime /opt/jdk-11-mini-runtime RUN mkdir /app COPY ./build/libs/kbhello-0.1.0.jar /app EXPOSE 8080 ENTRYPOINT [ "java", "-jar", "/app/kbhello-0.1.0.jar" ]
docker build -t hiroki . docker run -it --rm -p 8080:8080 hiroki
openjdk:8-jdk-alpine
イメージサイズ: 121MB
Dockerfile.openjdk8alp
FROM openjdk:8-jdk-alpine RUN mkdir /app COPY ./build/libs/kbhello-0.1.0.jar /app ENTRYPOINT [ "java", "-jar", "/app/kbhello-0.1.0.jar"]
docker build -t openjdk8alp . docker run -it --rm -p 8080:8080 openjdk8alp
openjdk:11-jdk-slim
イメージサイズ: 490MB
Dockerfile.openjdk11slim
FROM openjdk:11-jdk-slim RUN mkdir /app COPY ./build/libs/kbhello-0.1.0.jar /app ENTRYPOINT [ "java", "-jar", "/app/kbhello-0.1.0.jar"]
docker build -t openjdk11slim . docker run -it --rm -p 8080:8080 openjdk11slim
adoptopenjdk/openjdk11
ここ で adoptopenjdk を知る。 まず How to use this Image のようにイメージ作成。 イメージサイズ: 458MB
Dockerfile
FROM adoptopenjdk/openjdk11:latest RUN mkdir /app COPY ./build/libs/kbhello-0.1.0.jar /app ENTRYPOINT [ "java", "-jar", "/app/kbhello-0.1.0.jar"]
docker build -t adopt1 . docker run -it --rm -p 8080:8080 adopt1
adoptopenjdk/openjdk11:x86_64-alpine-jre-11.0.2.9
イメージサイズ: 153MB
Dockerfile.adoptjre11alp
FROM adoptopenjdk/openjdk11:x86_64-alpine-jre-11.0.2.9 RUN mkdir /app COPY ./build/libs/kbhello-0.1.0.jar /app ENTRYPOINT [ "java", "-jar", "/app/kbhello-0.1.0.jar"]
docker build -t adoptjre11alp . docker run -it --rm -p 8080:8080 adoptjre11alp
サイズ比較
$ docker images REPOSITORY SIZE hiroki 78.7MB openjdk8alp 121MB openjdk11slim 490MB adopt1 458MB adoptjre11alp 153MB
参考
- qiita Docker multi stage buildで変わるDockerfileの常識
- qiita OpenJDK11のdokcerイメージ(1GB)が大きいのでalpine linux+ jlinkで小さいイメージ(85MB)を作成する
- k11i.biz Java 11 リリース後のオススメ Docker イメージを考える
JDK11難民は続く。