Kubernetes が Docker Desktop で内部的にどのように機能するか

Docker Desktop を使用すると、Kubernetes 用のアプリケーションを簡単に開発できます。 インストールの複雑さとホストとの配線を隠すことで、スムーズな Kubernetes セットアップエクスペリエンスを提供します。 開発者は、Kubernetesのセットアップの詳細を扱うのではなく、自分の作業に完全に集中できます。 

このブログ投稿では、開発のユースケースと、それぞれの内部で何が起こるかについて説明します。 アプリケーションのデプロイを容易にするためにKubernetesがどのように設定されているか、ローカルで構築されているかどうか、およびデプロイされたアプリケーションへのアクセスのしやすさを分析します。

1. Kubernetes のセットアップ

Kubernetes は、以下に示すように、 Kubernetes 設定パネル から有効にすることができます。

スクリーンショット 2022 03 03 at 4.26. 午後40時

[Enable Kubernetes] チェックボックスをオンにして [適用] & [再起動] を押すと、単一ノードの Kubernetes クラスターのインストールがトリガーされます。開発者が行う必要があるのはこれだけです。

内部で正確に何が起こっているのですか? 

内部的には、Docker デスクトップ バックエンドと VM で次のアクションがトリガーされます。

  • 証明書の生成とクラスター構成
  • Kubernetes 内部コンポーネントのダウンロードとインストール
  • クラスタの起動
  • ネットワークとストレージ用の追加コントローラのインストール

次の図は、クラスターのセットアップにおける Docker Desktop の内部コンポーネント間の相互作用を示しています。

スクリーンショット 2022 03 03 at 4.27. 33午後

クラスター証明書、キー、構成ファイルの生成

Kubernetes では、内部コンポーネント間および外部コンポーネントとの認証済み接続に証明書とキーが必要です。 Docker Desktop は、主要な内部サービス (kubelet (ノード マネージャー)、サービス アカウント管理、フロントプロキシ、API サーバー、etcd コンポーネント) のこれらのサーバー証明書とクライアント 証明書 の生成を処理します。

Docker Desktop は kubeadm を使用して Kubernetes をインストールするため、 kubeadm ランタイムとクラスター全体の構成を作成する必要があります。 これには、クラスターのネットワークトポロジ、証明書、コントロールプレーンエンドポイントなどの構成が含まれます。 Docker デスクトップ固有の名前付けを使用し、ユーザーがカスタマイズすることはできません。 現在のコンテキスト名、ユーザー名、およびクラスター名は常に docker-desktop に設定されますが、クラスターのグローバル エンドポイントは DNS 名 https://kubernetesを使用していますドッカー内部:6443。ポート 6443 は、Kubernetes コントロール プレーンがバインドされている既定のポートです。 Docker Desktop は、ホスト上でこのポートを転送し、ホストに直接インストールされるコントロール プレーンとの通信を容易にします。

Kubernetes コンポーネントのダウンロードとインストール 

Docker デスクトップ VM 内では、 ライフサイクル サービス という名前の管理プロセスによって、Docker デーモンなどのサービスのデプロイと開始、およびそれらの状態の変更を通知します。

Kubernetes の証明書と構成が生成されると、ライフサイクル サービスに対して Kubernetes をインストールして起動するように要求されます。 要求には、セットアップに必要な証明書 (Kubernetes PKI) が含まれています。

その後、ライフサイクル サービスは、Docker Hub から Kubernetes 内部コンポーネントのすべてのイメージのプルを開始します。 これらの画像には、kubelet、kubeadm、kubectl、crictl などのバイナリが含まれており、これらは抽出されて '/usr/bin' に配置されます。

クラスタの起動

これらのバイナリが配置され、構成ファイルが正しいパスに書き込まれると、ライフサイクル サービスは 'kubeadm init' を実行してクラスターを初期化し、kubelet プロセスを開始します。 これは単一ノード クラスターのセットアップであるため、実行される kubelet インスタンスは 1 つだけです。

その後、ライフサイクル サービスは、Kubernetes が開始されたことを Docker Desktop ホスト サービスに通知するために、次のシステム ポッドが実行されるのを待機します: coredns、kube-controller-manager、kube-apiserver。 

追加のコントローラーをインストールする

Kubernetes 内部サービスが開始されると、Docker Desktop によって 、ストレージ プロビジョナーvpnkit コントローラーなどの追加のコントローラーのインストールがトリガーされます。 それらの役割は、再起動/アップグレード間でアプリケーションの状態を保持することと、デプロイ後にアプリケーションにアクセスする方法に関係します。

これらのコントローラーが起動して実行されると、Kubernetes クラスターが完全に動作し、Docker ダッシュボードにその状態が通知されます。

これで、kubectl コマンドを実行してアプリケーションをデプロイできるようになりました。

$ kubectl get svc
NAME       TYPE       CLUSTER-IP   EXTERNAL-IP     PORT(S)    	AGE
kubernetes ClusterIP  10.96.0.1    <none>    	   443/TCP    	1m

この状態でシステム ポッドを確認すると、次の値が返されます。

$ kubectl get pods -n kube-system
名前の準備完了状態が経過時間を再起動します
coredns-78fcd69978-7m52k 1/1 ランニング 0 99m
coredns-78fcd69978-mm22t 1/1 ランニング 0 99m
etcd-docker-デスクトップ1/1ランニング1 99m
kube-apiserver-docker-desktop 1/1 running 1 99m
kube-controller-manager-docker-desktop 1/1 Running 1 99m
kube-proxy-zctsm 1/1 ランニング 0 99m
kube-スケジューラ-ドッカー-デスクトップ1/1ランニング1 99m
ストレージプロビジョナー1/1ランニング0 98m
VPNキットコントローラ1/1ランニング0 98m

2. アプリケーションのデプロイとアクセス

例として、Docker デスクトップ チュートリアルである docker/get started のデプロイのための Kubernetes yaml を取り上げましょう。 これは、どこにでもデプロイできる汎用の Kubernetes yaml であり、Docker Desktop 固有の構成は含まれていません。

apiVersion: v1
kind: Service
metadata:
  name: tutorial
spec:
  ports:
  - name: 80-tcp
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    com.docker.project: tutorial
  type: LoadBalancer
status:
  loadBalancer: {}

---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    com.docker.project: tutorial
  name: tutorial
spec:
  replicas: 1
  selector:
    matchLabels:
      com.docker.project: tutorial
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        com.docker.project: tutorial
    spec:
      containers:
      - image: docker/getting-started
        name: tutorial
        ports:
        - containerPort: 80
          protocol: TCP
        resources: {}
      restartPolicy: Always
status: {}

Docker デスクトップのホストで、ターミナルを開き、次のコマンドを実行します。

$ kubectl apply -f tutorial.yaml
service/tutorial created
deployment.apps/tutorial created

チェックサービス:

$ kubectl get svc
NAME       TYPE   	CLUSTER-IP     EXTERNAL-IP   PORT(S)       AGE
kubernetes ClusterIP  	10.96.0.1      <none>        443/TCP       118m
tutorial   LoadBalancer 10.98.217.243  localhost     80:31575/TCP  12m

ロード バランサーの種類のサービスは、Kubernetes クラスターの外部に公開されます。 ブラウザーを開いて localhost:80 に移動すると、Docker チュートリアルが表示されます。

ここで注意する必要があるのは、サービスへのアクセスは、ホスト上で直接実行しているかのように簡単であるということです。 開発者は、追加の構成について心配する必要はありません。 

これは、Docker Desktopがホスト上のサービスポートを公開して、ホスト上で直接アクセスできるようにするためです。 これは、以前にインストールされた追加のコントローラーを介して行われます。

Vpnkitコントローラ は、ホスト上のポートを開いて転送するポート転送サービスです

VM 内のポッドへの透過的な接続。 接続の転送に使用されています

を Kubernetes にデプロイされたロードバランサータイプのサービスに追加します。

3. 開発とテストの内部ループを高速化

クラスター内のアプリケーションをデプロイしてアクセスする方法を見てきました。 ただし、開発サイクルは、開発者がアプリケーションのコードを変更し、継続的にテストすることで構成されます。 

ローカルで開発しているアプリケーションを例にとってみましょう。 

$ cat main.go
package main

import (
	"fmt"
	"log"
	"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
	fmt.Println(r.URL.RawQuery)
	fmt.Fprintf(w, `
          ##         .
    ## ## ##        ==
 ## ## ## ## ##    ===
/"""""""""""""""""\___/ ===
{                       /  ===-
\______ O           __/
 \    \         __/
  \____\_______/
	
Hello from Docker!

`)
}
func main() {
	http.HandleFunc("/", handler)
	log.Fatal(http.ListenAndServe(":80", nil))
}

アプリケーションを Docker イメージとしてビルドおよびパッケージ化するための Dockerfile:

$ cat Dockerfile 
FROM golang:1.16 AS build

WORKDIR /compose/hello-docker
COPY main.go main.go
RUN CGO_ENABLED=0 go build -o hello main.go

FROM scratch
COPY --from=build /compose/hello-docker/hello /usr/local/bin/hello
CMD ["/usr/local/bin/hello"]

アプリケーションをビルドするには、通常どおり docker build を実行します。

$ docker images
REPOSITORY   TAG   	IMAGE ID   CREATED   SIZE


$ docker build -t hellodocker .
[+] Building 0.9s (10/10) FINISHED                               	 
 => [internal] load build definition from Dockerfile         	0.0s
 => => transferring dockerfile: 38B                          	0.0s
. . . 
 => => naming to docker.io/library/hellodocker               	0.0s

Dockerエンジンキャッシュに保存されているビルドの結果のイメージを確認できます。

$ docker images
REPOSITORY      TAG   	IMAGE ID   	CREATED     	SIZE
hellodocker     latest	903fe47400c8    4 hours ago 	6.13MB

しかし今、私たちは問題を抱えています!

Kubernetesは通常、レジストリからイメージをプルするため、変更のたびにビルドしたイメージをプッシュおよびプルする必要があります。 Docker Desktop は、  Dockershim を使用して Docker エンジンと Kubernetes の間でイメージ キャッシュを共有することで、この摩擦を取り除きます。 Dockershim は Kubernetes の内部コンポーネントであり、kubelet と Docker Engine の間の変換レイヤーのように機能します。

開発では、Kubernetes が Docker エンジンのイメージ キャッシュに格納されているイメージからコンテナーを作成できるという重要な利点があります。 イメージをローカルでビルドし、最初にレジストリにプッシュすることなくすぐにテストできます。 

チュートリアル の例の kubernetes yaml で、イメージ名を hellodocker に更新し、イメージのプル ポリシーを IfNotPresent に設定します。これにより、ローカル キャッシュのイメージが使用されるようになります。

...
      containers:
        - name: hello
          image: hellodocker
          ports:
            - containerPort: 80
              protocol: TCP
          resources: {}
          imagePullPolicy: IfNotPresent
      restartPolicy: Always
...

再展開すると、新しい更新プログラムが適用されます。

$ kubectl apply -f tutorial.yaml
service/tutorial configured
deployment.apps/tutorial configured

$ kubectl get svc
NAME       TYPE       	CLUSTER-IP       EXTERNAL-IP   PORT(S) 	     AGE
tutorial   LoadBalancer 10.109.236.243   localhost     80:31371/TCP  4s
kubernetes ClusterIP  	10.96.0.1        <none>        443/TCP       6h56m

$ curl localhost:80

      	##     	.
	## ## ##    	==
 ## ## ## ## ##	===
/"""""""""""""""""\___/ ===
{                   	/  ===-
\______ O       	__/
 \	\     	__/
  \____\_______/


Hello from Docker!

クラスターからアプリケーションを削除するには、次のコマンドを実行します。

$ kubectl delete -f tutorial.yaml

4. Kubernetes のアップデート

この場合、Docker デスクトップの更新後に Kubernetes のバージョンをアップグレードできます。 ただし、新しい Kubernetes バージョンが Docker Desktop に追加された場合、ユーザーは最新バージョンを使用するために現在のクラスターをリセットする必要があります。

ポッドはエフェメラルとして設計されているため、デプロイされたアプリケーションは通常、状態を永続ボリュームに保存します。 これは、ストレージ プロビジョナー がローカルストレージデータの永続化に役立つ場所です。

結論

Docker Desktopは、ユーザーの介入なしに動作することを目的とした、強固なホスト統合を備えたKubernetesインストールを提供します。 セットアップを気にせずに Kubernetes クラスターを必要とする開発者は、Docker Desktop をインストールするだけで、Kubernetes クラスターを数分ですべて配置できます。 

Docker Desktop を入手するには、 Docker のドキュメントの指示に従ってください。 また、 Kubernetes を有効にする方法に関する専用ガイドも含まれています。

さらに詳しく