tag:crieit.net,2005:https://crieit.net/tags/Kubernetes/feed 「Kubernetes」の記事 - Crieit Crieitでタグ「Kubernetes」に投稿された最近の記事 2022-05-15T23:54:05+09:00 https://crieit.net/tags/Kubernetes/feed tag:crieit.net,2005:PublicArticle/18184 2022-05-04T05:16:16+09:00 2022-05-15T23:54:05+09:00 https://crieit.net/posts/Docker-Kubernetes-gitLab DockerとKubernetes <h1 id="0 前提"><a href="#0+%E5%89%8D%E6%8F%90">0 前提</a></h1> <p>Oracle LinuxとWindows</p> <h1 id="1 環境構築"><a href="#1+%E7%92%B0%E5%A2%83%E6%A7%8B%E7%AF%89">1 環境構築</a></h1> <p>準備</p> <h2 id="1-1 Dockerオフラインインストール"><a href="#1-1+Docker%E3%82%AA%E3%83%95%E3%83%A9%E3%82%A4%E3%83%B3%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">1-1 Dockerオフラインインストール</a></h2> <p>参考にしたURLは<code>https://qiita.com/kod314/items/e574ac12c23598e0d903</code>。<br /> オンラインインストールの場合は、<br /> <a target="_blank" rel="nofollow noopener" href="https://qiita.com/kichise/items/f8e56c6d2d08eaf4a6a0">https://qiita.com/kichise/items/f8e56c6d2d08eaf4a6a0</a><br /> の手順に従えば可能。</p> <p>今回はオフラインインストールを実行しようと思う。社内規則によりDockerをインストールするサーバがインターネット接続できない場合がある。その場合、インターネット接続できる自席端末からネットに接続してDockerのインストーラーをダウンロード。それをDockerをインストールしたいサーバに転送して実行させる。</p> <h3 id="1-1-1 OS確認"><a href="#1-1-1+OS%E7%A2%BA%E8%AA%8D">1-1-1 OS確認</a></h3> <p>まずはOSのversionを確認。</p> <pre><code>$ uname -a Linux publicpc1 5.4.17-2136.305.5.3.el8uek.x86_64 #2 SMP Thu Mar 17 10:45:33 PDT 2022 x86_64 x86_64 x86_64 GNU/Linux </code></pre> <p>より詳細</p> <pre><code>#cat /etc/os-release NAME="Oracle Linux Server" VERSION="8.5" ID="ol" ID_LIKE="fedora" VARIANT="Server" VARIANT_ID="server" VERSION_ID="8.5" PLATFORM_ID="platform:el8" PRETTY_NAME="Oracle Linux Server 8.5" ANSI_COLOR="0;31" CPE_NAME="cpe:/o:oracle:linux:8:5:server" HOME_URL="https://linux.oracle.com/" BUG_REPORT_URL="https://bugzilla.oracle.com/" ORACLE_BUGZILLA_PRODUCT="Oracle Linux 8" ORACLE_BUGZILLA_PRODUCT_VERSION=8.5 ORACLE_SUPPORT_PRODUCT="Oracle Linux" ORACLE_SUPPORT_PRODUCT_VERSION=8.5 </code></pre> <p>Linuxカーネルの確認</p> <pre><code>$ hostnamectl Static hostname: publicpc1 Icon name: computer-vm Chassis: vm Machine ID: 4c3dc5bfa43b47b8b66789ce778a0711 Boot ID: 226a196eedc746e2848a6f15e9afeb0b Virtualization: kvm Operating System: Oracle Linux Server 8.5 CPE OS Name: cpe:/o:oracle:linux:8:5:server Kernel: Linux 5.4.17-2136.305.5.3.el8uek.x86_64 Architecture: x86-64 </code></pre> <p>x86_64と記載されているので、Intel(AMD)の64bitオペレーティングシステムであることがわかる。</p> <h3 id="1-1-2 Docker engineをインストール"><a href="#1-1-2+Docker+engine%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">1-1-2 Docker engineをインストール</a></h3> <p>Docker本体であるDocker Engineと、同時に複数のコンテナを操作するツールであるDocker Composeをダウンロードする。<br /> 参考にした公式:https://docs.docker.com/engine/install/binaries/</p> <p>まずはdocker本体<br /> <a target="_blank" rel="nofollow noopener" href="https://download.docker.com/linux/static/stable/x86_64/">https://download.docker.com/linux/static/stable/x86_64/</a><br /> →バージョンがいろいろあるので、最新のdocker-20.10.9.tgz をダウンロードしてみた。<br /> 自分の端末(クライアント側にダウンロードしたファイルをLinuxサーバに転送してから解凍する。</p> <pre><code>$ ls -al /home/opc/docker-20.10.9.tgz -rw-r--r--. 1 opc opc 63350495 May 4 04:23 /home/opc/docker-20.10.9.tgz </code></pre> <p>展開</p> <pre><code>$ tar zxvf docker-20.10.9.tgz </code></pre> <p>すると、カレントディレクトリにdockerディレクトリが作成される。<br /> dockerディレクトリの中身を<code>/usr/bin/</code>配下にコピーする。</p> <pre><code>$ sudo cp docker/* /usr/bin/ </code></pre> <p>試しに起動するには</p> <pre><code>$ sudo dockerd & </code></pre> <h3 id="1-1-3 Docker Composeをインストール"><a href="#1-1-3+Docker+Compose%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">1-1-3 Docker Composeをインストール</a></h3> <p>続いてはdocker-compose<br /> インストール手順は以下に記載されているので以降この指示に従う。<br /> <a target="_blank" rel="nofollow noopener" href="https://github.com/docker/compose/blob/v2/README.md">https://github.com/docker/compose/blob/v2/README.md</a></p> <p>さきほど(1-1-1節)でOSとCPUを確認したので、<br /> それに従って<code>docker-compose-linux-x86_64</code>をダウンロードする。<br /> <a target="_blank" rel="nofollow noopener" href="https://github.com/docker/compose/releases">https://github.com/docker/compose/releases</a></p> <p>自分のwindows端末(クライアント側)にダウンロードした<code>docker-compose-linux-x86_64</code>をdockerをインストールしたLinuxサーバに転送。<br /> 転送したら、バイナリファイルの名前を<code>docker-compose</code>にリネーム。</p> <pre><code>$ mv docker-compose-linux-x86_64 docker-compose </code></pre> <p>docker-composeをいどうする。移動する先は目的に応じて移動先が異なる。<br /> 今回は</p> <pre><code>$ sudo mv docker-compose /usr/local/bin/ $ sudo chmod +x /usr/local/bin/docker-compose $ docker-compose -v Docker Compose version v2.5.0 </code></pre> <h3 id="1-1-4 Docker イメージのオフラインで利用する"><a href="#1-1-4+Docker+%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8%E3%81%AE%E3%82%AA%E3%83%95%E3%83%A9%E3%82%A4%E3%83%B3%E3%81%A7%E5%88%A9%E7%94%A8%E3%81%99%E3%82%8B">1-1-4 Docker イメージのオフラインで利用する</a></h3> <pre><code>$ tar zxvf helloworld_img.tar.gz $ docker load < helloworld_img # dockerイメージをload $ docker images # hello-worldイメージが存在することを確認 </code></pre> <h3 id="1-1-5 Dockerグループ作成"><a href="#1-1-5+Docker%E3%82%B0%E3%83%AB%E3%83%BC%E3%83%97%E4%BD%9C%E6%88%90">1-1-5 Dockerグループ作成</a></h3> <p>Docker daemonはrootユーザで実行しなければならず、毎回sudoを使うのは面倒である。<br /> その場合、dockerグループを作成してそこに任意のユーザを所属させてあげる。</p> <pre><code>groupadd docker usermod -aG docker opc </code></pre> <h3 id="1-1-6 トラブルシュート"><a href="#1-1-6+%E3%83%88%E3%83%A9%E3%83%96%E3%83%AB%E3%82%B7%E3%83%A5%E3%83%BC%E3%83%88">1-1-6 トラブルシュート</a></h3> <p>docklerをサービスでenebleにしようと思ったができなかった。</p> <pre><code>[root@publicpc1 system]# systemctl enable docker Failed to enable unit: Unit file docker.service does not exist. </code></pre> <p>以下のサイトを参考に対応してみた。<br /> <a target="_blank" rel="nofollow noopener" href="https://jhooq.com/docker-daemon-centos/">https://jhooq.com/docker-daemon-centos/</a></p> <p>/usr/lib/systemd/system配下にdocker.socketファイルを作成し以下の内容を記載した。</p> <pre><code>[Unit] Description=Docker Socket for the API [Socket] ListenStream=/var/run/docker.sock SocketMode=0660 SocketUser=root SocketGroup=docker [Install] WantedBy=sockets.target </code></pre> <p>続いて、/usr/lib/systemd/system/配下に<code>docker.service</code>を作成する。</p> <pre><code>[Unit] Description=Docker Application Container Engine Documentation=https://docs.docker.com After=network-online.target docker.socket firewalld.service containerd.service Wants=network-online.target Requires=docker.socket containerd.service [Service] Type=notify #the default is not to use systemd for cgroups because the delegate issues still #exists and systemd currently does not support the cgroup feature set required #for containers run by docker ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock ExecReload=/bin/kill -s HUP $MAINPID TimeoutSec=0 RestartSec=2 Restart=always #Note that StartLimit* options were moved from "Service" to "Unit" in systemd 229. #Both the old, and new location are accepted by systemd 229 and up, so using the old location #to make them work for either version of systemd. StartLimitBurst=3 #Note that StartLimitInterval was renamed to StartLimitIntervalSec in systemd 230. #Both the old, and new name are accepted by systemd 230 and up, so using the old name to make #this option work for either version of systemd. StartLimitInterval=60s #Having non-zero Limit*s causes performance problems due to accounting overhead #in the kernel. We recommend using cgroups to do container-local accounting. LimitNOFILE=infinity LimitNPROC=infinity LimitCORE=infinity #Comment TasksMax if your systemd version does not support it. #Only systemd 226 and above support this option. TasksMax=infinity #set delegate yes so that systemd does not reset the cgroups of docker containers Delegate=yes #kill only the docker process, not all processes in the cgroup KillMode=process OOMScoreAdjust=-500 [Install] WantedBy=multi-user.target </code></pre> <p>この中身をみると<code>Requires=docker.socket containerd.service</code>と記載されている通り、containerd.serviceが必要。なので/usr/lib/systemd/system配下にcontainerd.serviceサービスを作成する必要がある。</p> <pre><code>#Copyright The containerd Authors. #Licensed under the Apache License, Version 2.0 (the "License"); #you may not use this file except in compliance with the License. #You may obtain a copy of the License at #http://www.apache.org/licenses/LICENSE-2.0 #Unless required by applicable law or agreed to in writing, software #distributed under the License is distributed on an "AS IS" BASIS, #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #See the License for the specific language governing permissions and #limitations under the License. [Unit] Description=containerd container runtime Documentation=https://containerd.io After=network.target local-fs.target [Service] ExecStartPre=-/sbin/modprobe overlay ExecStart=/usr/bin/containerd Type=notify Delegate=yes KillMode=process Restart=always RestartSec=5 #Having non-zero Limit*s causes performance problems due to accounting overhead #in the kernel. We recommend using cgroups to do container-local accounting. LimitNPROC=infinity LimitCORE=infinity LimitNOFILE=infinity #Comment TasksMax if your systemd version does not supports it. #Only systemd 226 and above support this version. TasksMax=infinity OOMScoreAdjust=-999 [Install] WantedBy=multi-user.target </code></pre> <p>上記を作成する。</p> <p>ちゃんとリロードしとく。</p> <pre><code>systemctl daemon-reload </code></pre> <h2 id="1-2.Kubernetesの準備"><a href="#1-2.Kubernetes%E3%81%AE%E6%BA%96%E5%82%99">1-2.Kubernetesの準備</a></h2> <h3 id="1-2-1. インストール"><a href="#1-2-1.+%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">1-2-1. インストール</a></h3> <p>オフライン環境でKubernetesを構築する手順。<br /> 手順の参考にしたのは以下<br /> <a target="_blank" rel="nofollow noopener" href="https://docs.genesys.com/Documentation/GCXI/latest/Dep/DockerOffline">https://docs.genesys.com/Documentation/GCXI/latest/Dep/DockerOffline</a></p> <p>まずはネットにつながる端末から</p> <pre><code>$ pwd /etc/yum.repos.d $ cat kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64 enabled=1 gpgcheck=1 repo_gpgcheck=1 gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg </code></pre> <p>以下のコマンドを実行してファイルをダウンロード。<br /> <code><your_rpm_dir></code>の部分は自分で適当なディレクトリを作成して<br /> そこのパスを指定。</p> <pre><code>yumdownloader --assumeyes --destdir= --resolve yum-utils kubeadm-1.21.* kubelet-1.21.* kubectl-1.21.* ebtables </code></pre> <p>続いて、ダウンロードしたファイルをインストールしていく。</p> <pre><code>yum install -y --cacheonly --disablerepo=* /*.rpm </code></pre> <p>インストールする際、バージョンが異なるファイルが存在してインストールエラーになるかもしれない。<br /> その場合は、必要のないバージョンのファイルは削除してから<br /> 再度インストールするとうまくいく。<br /> うまくいくと以下のようになる。</p> <pre><code>Complete! </code></pre> <p>必要なイメージが揃っているか確認してみよう。</p> <pre><code>$ kubeadm config images list I0504 23:15:36.977910 309762 version.go:254] remote version is much newer: v1.24.0; falling back to: stable-1.21 k8s.gcr.io/kube-apiserver:v1.21.12 k8s.gcr.io/kube-controller-manager:v1.21.12 k8s.gcr.io/kube-scheduler:v1.21.12 k8s.gcr.io/kube-proxy:v1.21.12 k8s.gcr.io/pause:3.4.1 k8s.gcr.io/etcd:3.4.13-0 k8s.gcr.io/coredns/coredns:v1.8.0 </code></pre> <h3 id="1-2-2. kubectlの概要"><a href="#1-2-2.+kubectl%E3%81%AE%E6%A6%82%E8%A6%81">1-2-2. kubectlの概要</a></h3> <p>参考URL:https://kubernetes.io/ja/docs/reference/kubectl/_print/<br /> Kubernetesクラスタを操作するコマンド</p> <h1 id="2.Docker入門"><a href="#2.Docker%E5%85%A5%E9%96%80">2.Docker入門</a></h1> kawai_mizugorou tag:crieit.net,2005:PublicArticle/16133 2020-10-14T22:58:44+09:00 2020-10-14T22:58:44+09:00 https://crieit.net/posts/GKE-upgrade-network-plugin GKE を upgrade したら network plugin が死んだので対応した作業記録 <p><strong>Qrunch から引っ越し</strong></p> <p>※ GKE のネガキャンではありません。むしろ好きでちゃんと運用したいからこそ残しているものです。</p> <p>軽い気持ちで GKE を <code>1.11.2-gke.18</code> から <code>1.11.3-gke.18</code> に upgrade した。</p> <p>そして何気なく Deployment を作ったが Pod が起動しない。<br /> <code>kubectl describe pod</code> で見るとおかしな event が記録されているのが分かった。</p> <pre><code>Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 3m default-scheduler Successfully assigned xyz/hoge-5b4db95bf5-krmjc to gke-gke01-preemptible01-e5cc132c-77fz Warning FailedCreatePodSandBox 3m kubelet, gke-gke01-preemptible01-e5cc132c-77fz Failed create pod sandbox: rpc error: code = Unknown desc = failed to set up sandbox container "af7579fb0a4ad73cfaeb083ef47de36b7f84aed7f160685384354ed0d8512339" network for pod "hoge-5b4db95bf5-krmjc": NetworkPlugin cni failed to set up pod "hoge-5b4db95bf5-krmjc_xyz" network: stat /var/lib/calico/nodename: no such file or directory: check that the calico/node container is running and has mounted /var/lib/calico/ Warning FailedCreatePodSandBox 3m kubelet, gke-gke01-preemptible01-e5cc132c-77fz Failed create pod sandbox: rpc error: code = Unknown desc = failed to set up sandbox container "56c9b914c9f3c940c8d5479807820814e43f6716a263ca5c9a1bf53cef6ae252" network for pod "hoge-5b4db95bf5-krmjc": NetworkPlugin cni failed to set up pod "hoge-5b4db95bf5-krmjc_xyz" network: stat /var/lib/calico/nodename: no such file or directory: check that the calico/node container is running and has mounted /var/lib/calico/ Warning FailedCreatePodSandBox 3m kubelet, gke-gke01-preemptible01-e5cc132c-77fz Failed create pod sandbox: rpc error: code = Unknown desc = failed to set up sandbox container "10bdc42cc20617283e18f67a4e4d171eecb4182dd0e9f7114465c4047e5f3c12" network for pod "hoge-5b4db95bf5-krmjc": NetworkPlugin cni failed to set up pod "hoge-5b4db95bf5-krmjc_xyz" network: stat /var/lib/calico/nodename: no such file or directory: check that the calico/node container is running and has mounted /var/lib/calico/ </code></pre> <p>このクラスタは NetworkPolicy を有効にしているため、Calico が動作している。<br /> kube-system namespace の Pod を見てみると、何やらひどいことが起きているようだ。</p> <pre><code>$ kubectl -n kube-system get pod | grep -E '^NAME|calico' NAME READY STATUS RESTARTS AGE calico-node-974fs 1/2 CrashLoopBackOff 9 24m calico-node-fx464 1/2 CrashLoopBackOff 9 24m calico-node-kzhsr 1/2 CrashLoopBackOff 9 24m calico-node-q4ktd 1/2 CrashLoopBackOff 9 24m calico-node-qwqsx 1/2 CrashLoopBackOff 9 24m calico-node-vertical-autoscaler-547d98499d-l7rd2 1/1 Running 0 6h calico-typha-5977794b76-dmxjr 0/1 CrashLoopBackOff 9 24m calico-typha-horizontal-autoscaler-5ff7f558cc-2ksbc 1/1 Running 0 19h calico-typha-vertical-autoscaler-5d4bf57df5-hp8r6 1/1 Running 0 6h </code></pre> <p>network plugin が動作しなくなっているため、既存 Pod はまだ生き延びられるが、新規 Pod が起動しない状態になっているようだ。</p> <p><code>calico-node</code> の DaemonSet を YAML で出力して中身をみると、<code>v2.6.11</code> だったはずの calico のイメージが <code>v3.2.4</code> に上がっていた。<br /> (バージョンを確認したのは、別件で GKE の問い合わせをしていて Calico のバージョンが変わりそうな気配を感じていたため)</p> <p>別途 NetworkPolicy を有効にした新規クラスタを作成してみて、そちらでは問題無く動作することを確認。</p> <p>問題が起きている方のクラスタで <code>calico-node</code> の Pod のログを見ると以下のようになっていた。</p> <pre><code>2018-12-05 05:16:41.622 [INFO][8] startup.go 252: Early log level set to info 2018-12-05 05:16:41.623 [INFO][8] startup.go 268: Using NODENAME environment for node name 2018-12-05 05:16:41.623 [INFO][8] startup.go 280: Determined node name: gke-gke00-preemptible01-df3d5d39-m2h6 2018-12-05 05:16:41.624 [INFO][8] startup.go 303: Checking datastore connection 2018-12-05 05:16:41.638 [INFO][8] startup.go 327: Datastore connection verified 2018-12-05 05:16:41.638 [INFO][8] startup.go 100: Datastore is ready 2018-12-05 05:16:41.651 [INFO][8] startup.go 1052: Running migration 2018-12-05 05:16:41.651 [INFO][8] migrate.go 866: Querying current v1 snapshot and converting to v3 2018-12-05 05:16:41.651 [INFO][8] migrate.go 875: handling FelixConfiguration (global) resource 2018-12-05 05:16:41.658 [INFO][8] migrate.go 875: handling ClusterInformation (global) resource 2018-12-05 05:16:41.658 [INFO][8] migrate.go 875: skipping FelixConfiguration (per-node) resources - not supported 2018-12-05 05:16:41.658 [INFO][8] migrate.go 875: handling BGPConfiguration (global) resource 2018-12-05 05:16:41.658 [INFO][8] migrate.go 600: Converting BGP config -> BGPConfiguration(default) 2018-12-05 05:16:41.677 [INFO][8] migrate.go 875: skipping Node resources - these do not need migrating 2018-12-05 05:16:41.677 [INFO][8] migrate.go 875: skipping BGPPeer (global) resources - these do not need migrating 2018-12-05 05:16:41.677 [INFO][8] migrate.go 875: handling BGPPeer (node) resources 2018-12-05 05:16:41.687 [INFO][8] migrate.go 875: skipping HostEndpoint resources - not supported 2018-12-05 05:16:41.687 [INFO][8] migrate.go 875: skipping IPPool resources - these do not need migrating 2018-12-05 05:16:41.687 [INFO][8] migrate.go 875: skipping GlobalNetworkPolicy resources - these do not need migrating 2018-12-05 05:16:41.687 [INFO][8] migrate.go 875: skipping Profile resources - these do not need migrating 2018-12-05 05:16:41.688 [INFO][8] migrate.go 875: skipping WorkloadEndpoint resources - these do not need migrating 2018-12-05 05:16:41.688 [INFO][8] migrate.go 875: data converted successfully 2018-12-05 05:16:41.688 [INFO][8] migrate.go 866: Storing v3 data 2018-12-05 05:16:41.688 [INFO][8] migrate.go 875: Storing resources in v3 format 2018-12-05 05:16:41.752 [INFO][8] migrate.go 1151: Failed to create resource Key=BGPConfiguration(default) error=resource does not exist: BGPConfiguration(default) with error: the server could not find the requested resource (post BGPConfigurations.crd.projectcalico.org) 2018-12-05 05:16:41.753 [ERROR][8] migrate.go 884: Unable to store the v3 resources 2018-12-05 05:16:41.753 [INFO][8] migrate.go 875: cause: resource does not exist: BGPConfiguration(default) with error: the server could not find the requested resource (post BGPConfigurations.crd.projectcalico.org) 2018-12-05 05:16:41.753 [ERROR][8] startup.go 107: Unable to ensure datastore is migrated. error=Migration failed: error storing converted data: resource does not exist: BGPConfiguration(default) with error: the server could not find the requested resource (post BGPConfigurations.crd.projectcalico.org) 2018-12-05 05:16:41.753 [WARNING][8] startup.go 1066: Terminating </code></pre> <p>新規構築したクラスタの <code>calico-node</code> の Pod のログと見比べると <code>migrate.go</code> の行が存在しない。<br /> <code>2018-12-05 05:16:41.651 [INFO][8] startup.go 1052: Running migration</code> という部分が鍵と思われる。</p> <p><code>startup.go</code> は <a target="_blank" rel="nofollow noopener" href="https://github.com/projectcalico/node.git">projectcalico/node</a> を見れば良さそうだが、<br /> <code>migrate.go</code> は <a target="_blank" rel="nofollow noopener" href="https://github.com/projectcalico/libcalico-go">projectcalico/libcalico-go</a> にあるようだ。<br /> libcalico-go のバージョンはどれを使っているのか分からないが、ログから BGPConfiguration を作れていない様子がうかがえる。</p> <p>Kubernetes における Calico は CustomResourceDefinition として設定を管理しているらしいので、crd の定義を調べる</p> <pre><code>$ kubectl get crd NAME AGE backendconfigs.cloud.google.com 22h clusterinformations.crd.projectcalico.org 22h felixconfigurations.crd.projectcalico.org 22h globalbgpconfigs.crd.projectcalico.org 22h globalfelixconfigs.crd.projectcalico.org 22h globalnetworkpolicies.crd.projectcalico.org 22h globalnetworksets.crd.projectcalico.org 22h hostendpoints.crd.projectcalico.org 22h ippools.crd.projectcalico.org 22h networkpolicies.crd.projectcalico.org 22h scalingpolicies.scalingpolicy.kope.io 22h </code></pre> <p>ログには<br /> <code>the server could not find the requested resource (post BGPConfigurations.crd.projectcalico.org)</code><br /> と出ていて、実際に <code>bgpconfigurations.crd.projectcalico.org</code> は存在しない。</p> <p>とりあえず手動で CRD を追加してみたい。<br /> 内容が分からないので適当にググると <code>https://github.com/projectcalico/libcalico-go/blob/master/test/crds.yaml</code> が見つかった。</p> <p>元の CRD を残しておきつつ、この <code>crds.yaml</code> を適用してみる。</p> <pre><code>$ kubectl get crd -o yaml > crd-backup.yaml $ curl -LO https://raw.githubusercontent.com/projectcalico/libcalico-go/master/test/crds.yaml $ kubectl apply -f crds.yaml customresourcedefinition.apiextensions.k8s.io "globalfelixconfigs.crd.projectcalico.org" configured customresourcedefinition.apiextensions.k8s.io "globalbgpconfigs.crd.projectcalico.org" configured customresourcedefinition.apiextensions.k8s.io "ippools.crd.projectcalico.org" configured customresourcedefinition.apiextensions.k8s.io "bgppeers.crd.projectcalico.org" created customresourcedefinition.apiextensions.k8s.io "globalnetworkpolicies.crd.projectcalico.org" configured customresourcedefinition.apiextensions.k8s.io "hostendpoints.crd.projectcalico.org" configured customresourcedefinition.apiextensions.k8s.io "felixconfigurations.crd.projectcalico.org" configured customresourcedefinition.apiextensions.k8s.io "bgpconfigurations.crd.projectcalico.org" created customresourcedefinition.apiextensions.k8s.io "clusterinformations.crd.projectcalico.org" configured customresourcedefinition.apiextensions.k8s.io "networkpolicies.crd.projectcalico.org" configured customresourcedefinition.apiextensions.k8s.io "globalnetworksets.crd.projectcalico.org" configured </code></pre> <p>bgppeers.crd.projectcalico.org と bgpconfigurations.crd.projectcalico.org が新規作成されたようだ。<br /> CRD が作られたので、CrashLoopBackOff になっていた <code>calico-node</code> や <code>calico-typha</code> の Pod を消して再作成させる。</p> <pre><code>$ kubectl -n kube-system get pod -l k8s-app=calico-node $ kubectl -n kube-system delete pod -l k8s-app=calico-node $ kubectl -n kube-system get pod -l k8s-app=calico-typha $ kubectl -n kube-system delete pod -l k8s-app=calico-typha </code></pre> <p>これでしばらく放置しておくと、<code>calico-node</code> や <code>calico-typha</code> の Pod が起動し、他の Pod も起動するようになった。</p> <p><code>migrate.go</code> が成功した部分のログは以下のようなものだった。</p> <pre><code>2018-12-05 05:45:51.223 [INFO][8] startup.go 1052: Running migration 2018-12-05 05:45:51.223 [INFO][8] migrate.go 866: Querying current v1 snapshot and converting to v3 2018-12-05 05:45:51.223 [INFO][8] migrate.go 875: handling FelixConfiguration (global) resource 2018-12-05 05:45:51.232 [INFO][8] migrate.go 875: handling ClusterInformation (global) resource 2018-12-05 05:45:51.232 [INFO][8] migrate.go 875: skipping FelixConfiguration (per-node) resources - not supported 2018-12-05 05:45:51.232 [INFO][8] migrate.go 875: handling BGPConfiguration (global) resource 2018-12-05 05:45:51.232 [INFO][8] migrate.go 600: Converting BGP config -> BGPConfiguration(default) 2018-12-05 05:45:51.245 [INFO][8] migrate.go 875: skipping Node resources - these do not need migrating 2018-12-05 05:45:51.245 [INFO][8] migrate.go 875: skipping BGPPeer (global) resources - these do not need migrating 2018-12-05 05:45:51.245 [INFO][8] migrate.go 875: handling BGPPeer (node) resources 2018-12-05 05:45:51.255 [INFO][8] migrate.go 875: skipping HostEndpoint resources - not supported 2018-12-05 05:45:51.255 [INFO][8] migrate.go 875: skipping IPPool resources - these do not need migrating 2018-12-05 05:45:51.255 [INFO][8] migrate.go 875: skipping GlobalNetworkPolicy resources - these do not need migrating 2018-12-05 05:45:51.255 [INFO][8] migrate.go 875: skipping Profile resources - these do not need migrating 2018-12-05 05:45:51.255 [INFO][8] migrate.go 875: skipping WorkloadEndpoint resources - these do not need migrating 2018-12-05 05:45:51.255 [INFO][8] migrate.go 875: data converted successfully 2018-12-05 05:45:51.255 [INFO][8] migrate.go 866: Storing v3 data 2018-12-05 05:45:51.255 [INFO][8] migrate.go 875: Storing resources in v3 format 2018-12-05 05:45:51.324 [INFO][8] migrate.go 875: success: resources stored in v3 datastore 2018-12-05 05:45:51.324 [INFO][8] migrate.go 866: Migrating IPAM data 2018-12-05 05:45:51.324 [INFO][8] migrate.go 875: no data to migrate - not supported 2018-12-05 05:45:51.324 [INFO][8] migrate.go 866: Data migration from v1 to v3 successful 2018-12-05 05:45:51.324 [INFO][8] migrate.go 875: check the output for details of the migrated resources 2018-12-05 05:45:51.324 [INFO][8] migrate.go 875: continue by upgrading your calico/node versions to Calico v3.x 2018-12-05 05:45:51.324 [INFO][8] startup.go 1056: Migration successful </code></pre> <p>本来は GKE 側で修正されることではないかと思うが、どうなるのだろう。</p> <h2 id="後日確認・追記 (12/14)"><a href="#%E5%BE%8C%E6%97%A5%E7%A2%BA%E8%AA%8D%E3%83%BB%E8%BF%BD%E8%A8%98+%2812%2F14%29">後日確認・追記 (12/14)</a></h2> <ul> <li>GKE の Release Notes の <a target="_blank" rel="nofollow noopener" href="https://cloud.google.com/kubernetes-engine/release-notes">Known Issues</a> (抜粋):<br /> > Users upgrading to GKE 1.11.3 on clusters that use Calico network policies may experience failures due to a problem recreating the BGPConfigurations.crd.projectcalico.org resource. This problem does not affect newly-created clusters. This is expected to be fixed in the coming weeks.<br /> ><br /> > To work around this problem, you can create the BGPConfigurations.crd.projectcalico.org resource manually:</li> <li>Google の Issue Tracker: <a target="_blank" rel="nofollow noopener" href="https://issuetracker.google.com/issues/120255782">URGENT: after upgrading master nodes to 1.11.3 calico stopped working</a></li> <li>Calico の Issue: <a target="_blank" rel="nofollow noopener" href="https://github.com/projectcalico/calico/issues/2324">#2324</a></li> <li>Kubernetes の PullRequest: <a target="_blank" rel="nofollow noopener" href="https://github.com/kubernetes/kubernetes/pull/71868">#71868</a>, <a target="_blank" rel="nofollow noopener" href="https://github.com/kubernetes/kubernetes/pull/71682">#71682</a> <ul> <li>release-1.11 ブランチへのマージ: <a href="">#71918</a></li> <li>release-1.12 ブランチへのマージ: <a href="">#71882</a></li> <li>release-1.13 ブランチへのマージ: <a target="_blank" rel="nofollow noopener" href="https://github.com/kubernetes/kubernetes/pull/71883">#71883</a></li> <li>v1.13.1 のリリースで修正済み <a target="_blank" rel="nofollow noopener" href="https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.13.md#changelog-since-v1130">Changelog</a><br /> > Include CRD for BGPConfigurations, needed for calico 2.x to 3.x upgrade. (#71868, @satyasm)</li> <li>他のバージョンも次リリースされた時に修正されているはず。GKE もどこかで修正されることだろう。</li> </ul></li> </ul> albatross0 tag:crieit.net,2005:PublicArticle/16132 2020-10-14T22:57:52+09:00 2020-10-14T22:57:52+09:00 https://crieit.net/posts/GKE-kube-proxy-drain GKE の kube-proxy が drain されない理由 <p><strong>Qrunch から引っ越し</strong></p> <p>kubectl drain した時、テストで作った ownerReference の無い Pod がいたために怒られた。<br /> (これらの Pod は --force オプションで削除させることができる)</p> <p>ふと kube-proxy のことを思い出し、気になって調べた。</p> <p>GKE だと kube-proxy は /etc/kubernetes/manifests から起動されていて ownerReference は無いはずなのだが、どうやって drain を回避しているのだろうか。</p> <p>ファイルの manifest から起動しているのでそもそも API server 経由で実際の Pod 削除はできないのだが、Pod の定義だけ (一時的に) 削除することはあり得るのでは?</p> <p><code>pkg/kubectl/cmd/drain.go</code> を読むと分かる。</p> <pre><code>RunDrain() deleteOrEvictPodsSimple() getPodsForDeletion() deleteOrEvictPods() </code></pre> <p>kubectl drain コマンドにはいくつかのフィルタ条件があり、それらが適用されて残った Pod が<br /> <code>deleteOrEvictPods()</code> に渡される。</p> <p>各フィルタは <code>getPodsForDeletion()</code> の中で適用される。</p> <pre><code class="go">// getPodsForDeletion receives resource info for a node, and returns all the pods from the given node that we // are planning on deleting. If there are any pods preventing us from deleting, we return that list in an error. func (o *DrainOptions) getPodsForDeletion(nodeInfo *resource.Info) (pods []corev1.Pod, err error) { labelSelector, err := labels.Parse(o.PodSelector) if err != nil { return pods, err } podList, err := o.client.CoreV1().Pods(metav1.NamespaceAll).List(metav1.ListOptions{ LabelSelector: labelSelector.String(), FieldSelector: fields.SelectorFromSet(fields.Set{"spec.nodeName": nodeInfo.Name}).String()}) if err != nil { return pods, err } ws := podStatuses{} fs := podStatuses{} for _, pod := range podList.Items { podOk := true for _, filt := range []podFilter{o.daemonsetFilter, mirrorPodFilter, o.localStorageFilter, o.unreplicatedFilter} { filterOk, w, f := filt(pod) podOk = podOk && filterOk </code></pre> <ul> <li><code>-l, --selector=''</code> は drain 対象の Node をフィルタするもので、Pod に作用するものではない。</li> <li><code>--pod-selector=''</code> で drain で処理する Pod をフィルタする。<br /> 例えば、特定のラベルを持つ Pod を evict/delete 対象から外すには <code>--pod-selector='key!=value'</code> をつける</li> <li><code>--ignore-daemonsets</code> は DaemonSet から作成された Pod を除外する。(daemonsetFilter)</li> <li><code>--delete-local-data</code> は emptyDir ボリュームを持つ Pod を除外する。(localStorageFilter)</li> </ul> <p>ownerRefernece の有無は unreplicatedFilter で判定されるが、kube-proxy が除外されるのは mirrorPodFilter だった。</p> <pre><code class="go">func mirrorPodFilter(pod corev1.Pod) (bool, *warning, *fatal) { if _, found := pod.ObjectMeta.Annotations[corev1.MirrorPodAnnotationKey]; found { return false, nil, nil } return true, nil, nil } </code></pre> <p>annotation の定義は <code>pkg/apis/core/annotation_key_constants.go</code> を参照する。</p> <pre><code class="go"> // MirrorAnnotationKey represents the annotation key set by kubelets when creating mirror pods MirrorPodAnnotationKey string = "kubernetes.io/config.mirror" </code></pre> <p><code>kubernetes.io/config.mirror</code> という annotation を持っているかどうかでフィルタされているようだ。</p> <p>Mirror Pod って何だ?と思ってググると</p> <p>Statis Pod が API server 側で見えるようになっているもの (見えるだけで API から制御できないもの) のことを指すらしい。</p> <p>Static Pod は kubelet が API server ではなく ファイルや HTTP 経由で渡された manifest を元に 作成・起動した Pod のこと => <a target="_blank" rel="nofollow noopener" href="https://kubernetes.io/docs/tasks/administer-cluster/static-pod/">Static Pods</a></p> <p>調べてから見つけたが、詳しく説明している記事があった => <a target="_blank" rel="nofollow noopener" href="https://banzaicloud.com/blog/drain/">Draining Kubernetes nodes</a></p> albatross0 tag:crieit.net,2005:PublicArticle/15151 2019-06-22T23:35:52+09:00 2019-06-22T23:36:56+09:00 https://crieit.net/posts/minikube-2 minikubeを使ってみよう【その2】 <h1 id="レプリカの数を増やしてみよう"><a href="#%E3%83%AC%E3%83%97%E3%83%AA%E3%82%AB%E3%81%AE%E6%95%B0%E3%82%92%E5%A2%97%E3%82%84%E3%81%97%E3%81%A6%E3%81%BF%E3%82%88%E3%81%86">レプリカの数を増やしてみよう</a></h1> <h2 id="レプリカとは"><a href="#%E3%83%AC%E3%83%97%E3%83%AA%E3%82%AB%E3%81%A8%E3%81%AF">レプリカとは</a></h2> <p>アプリケーションコンテナのクローンです。<br /> レプリカを2に設定すると、同じアプリケーションコンテナが2つ起動します。<br /> 以下のような用途があります。</p> <ul> <li>コンテナの起動に失敗した場合 <ul> <li>残りのコンテナでサービスを継続する</li> </ul></li> <li>アプリケーションのアップデート中にサービスを中断したくない場合 <ul> <li>更新途中のコンテナ以外でサービスを継続する</li> </ul></li> </ul> <h2 id="レプリカの数を増やす"><a href="#%E3%83%AC%E3%83%97%E3%83%AA%E3%82%AB%E3%81%AE%E6%95%B0%E3%82%92%E5%A2%97%E3%82%84%E3%81%99">レプリカの数を増やす</a></h2> <p>運用で言う所の<strong>系</strong>の数ですね。</p> <pre><code># hello-minikubeというコンテナを4つに増やす $ kubectl scale deployments/hello-minikube --replicas=4 # 結果を確認する $ kubectl get deployments NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE hello-minikube 4 4 4 4 23h # podの中身を確認する $ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE hello-minikube-78c9fc5f89-68jtm 1/1 Running 0 14m 172.17.0.7 minikube hello-minikube-78c9fc5f89-6gsm8 1/1 Running 0 14m 172.17.0.8 minikube hello-minikube-78c9fc5f89-nwgvw 1/1 Running 1 23h 172.17.0.4 minikube hello-minikube-78c9fc5f89-x7m9g 1/1 Running 1 23h 172.17.0.2 minikube </code></pre> <h1 id="アプリケーションをアップデートする"><a href="#%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E3%82%A2%E3%83%83%E3%83%97%E3%83%87%E3%83%BC%E3%83%88%E3%81%99%E3%82%8B">アプリケーションをアップデートする</a></h1> <p>hello-minikubeというdockerイメージを使っていたpod内のアプリケーションを<code>jocatalin/kubernetes-bootcamp</code>というイメージに置き換えてみます。</p> <pre><code>$ kubectl set image deployments/hello-minikube hello-minikube=jocatalin/kubernetes-bootcamp:v2 # podの状況を取得する $ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE hello-minikube-5dbc4c9877-c57t4 0/1 ContainerCreating 0 8s <none> minikube hello-minikube-5dbc4c9877-v78sv 0/1 ContainerCreating 0 8s <none> minikube hello-minikube-78c9fc5f89-68jtm 1/1 Running 0 21m 172.17.0.7 minikube hello-minikube-78c9fc5f89-nwgvw 1/1 Running 1 23h 172.17.0.4 minikube hello-minikube-78c9fc5f89-x7m9g 1/1 Running 1 23h 172.17.0.2 minikube </code></pre> <p>更新作業中はいくつかコンテナを残した状態で順番に更新されていきます。</p> <h1 id="アプリケーションのロールバック"><a href="#%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E3%83%AD%E3%83%BC%E3%83%AB%E3%83%90%E3%83%83%E3%82%AF">アプリケーションのロールバック</a></h1> <p><code>rollout undo</code>コマンドで元に戻します。</p> <pre><code>$ kubectl rollout undo deployments/hello-minikube deployment.apps "hello-minikube" # podの状況を確認する $ kubectl get pods NAME READY STATUS RESTARTS AGE hello-minikube-5dbc4c9877-7zsqq 1/1 Terminating 0 6m hello-minikube-5dbc4c9877-c57t4 1/1 Running 0 6m hello-minikube-5dbc4c9877-jspcm 1/1 Terminating 0 6m hello-minikube-5dbc4c9877-v78sv 1/1 Terminating 0 6m hello-minikube-78c9fc5f89-5rfzt 0/1 ContainerCreating 0 2s hello-minikube-78c9fc5f89-cf2lk 1/1 Running 0 4s hello-minikube-78c9fc5f89-jrprp 1/1 Running 0 4s hello-minikube-78c9fc5f89-k7pq4 0/1 ContainerCreating 0 1s </code></pre> <p>並行してロールバックが行われているのがわかります。</p> <h1 id="参考リンク"><a href="#%E5%8F%82%E8%80%83%E3%83%AA%E3%83%B3%E3%82%AF">参考リンク</a></h1> <p><a target="_blank" rel="nofollow noopener" href="https://dev.classmethod.jp/cloud/kubernetes-tutorial-4/">[第4回]Kubernetesの公式チュートリアルをやって基本を押さえる -アプリのアップデート</a></p> ckoshien tag:crieit.net,2005:PublicArticle/15141 2019-06-22T00:21:08+09:00 2019-06-23T22:09:26+09:00 https://crieit.net/posts/minikube-1 minikubeを使ってみよう【その1】 <h1 id="kubernetesって?"><a href="#kubernetes%E3%81%A3%E3%81%A6%EF%BC%9F">kubernetesって?</a></h1> <p>dockerなどを使ってコンテナ化したアプリケーションの管理を行うOSSのオーケストレーションツール。<br /> <img src="https://d33wubrfki0l68.cloudfront.net/1567471e7c58dc9b7d9c65dcd54e60cbf5870daa/a2680/ja/_common-resources/images/flower.png" alt="image" /></p> <h2 id="kubernetesのアイコン、何に見えますか?"><a href="#kubernetes%E3%81%AE%E3%82%A2%E3%82%A4%E3%82%B3%E3%83%B3%E3%80%81%E4%BD%95%E3%81%AB%E8%A6%8B%E3%81%88%E3%81%BE%E3%81%99%E3%81%8B%EF%BC%9F">kubernetesのアイコン、何に見えますか?</a></h2> <p>船の舵だと思った方、正解です。<br /> dockerは多数の<strong>コンテナ</strong>を積んだ<strong>貨物船</strong>、<strong>kubernetes</strong>は<strong>装舵手</strong>です。</p> <p><a href="https://crieit.now.sh/upload_images/5b29b58a7326800278a9fd51aa7c6d9f5d0f79fc71ad2.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/5b29b58a7326800278a9fd51aa7c6d9f5d0f79fc71ad2.png?mw=700" alt="image" /></a></p> <h1 id="minikubeって?"><a href="#minikube%E3%81%A3%E3%81%A6%EF%BC%9F">minikubeって?</a></h1> <p><a target="_blank" rel="nofollow noopener" href="https://kubernetes.io/ja/docs/setup/minikube/">公式</a><br /> 開発・テスト向けの<strong>Kubernetes</strong>環境を構築するツール。</p> <h1 id="macにminikubeをインストール"><a href="#mac%E3%81%ABminikube%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">macにminikubeをインストール</a></h1> <h2 id="前提"><a href="#%E5%89%8D%E6%8F%90">前提</a></h2> <p>virtualboxがインストールされていること。</p> <h2 id="brewでインストール"><a href="#brew%E3%81%A7%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">brewでインストール</a></h2> <pre><code>$ brew cask install minikube </code></pre> <h2 id="minikubeの起動"><a href="#minikube%E3%81%AE%E8%B5%B7%E5%8B%95">minikubeの起動</a></h2> <pre><code>$ minikube start minikube v1.1.1 on darwin (amd64) 💿 Downloading Minikube ISO ... 131.29 MB / 131.29 MB [============================================] 100.00% 0s 🔥 Creating virtualbox VM (CPUs=2, Memory=2048MB, Disk=20000MB) ... 🐳 Configuring environment for Kubernetes v1.14.3 on Docker 18.09.6 💾 Downloading kubelet v1.14.3 💾 Downloading kubeadm v1.14.3 🚜 Pulling images ... 🚀 Launching Kubernetes ... ⌛ Verifying: apiserver proxy etcd scheduler controller dns 🏄 Done! kubectl is now configured to use "minikube" </code></pre> <p>minikubeイメージのダウンロードとvirtual box VMのcreateが始まるので多少時間がかかります。</p> <h2 id="コンテナ起動"><a href="#%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E8%B5%B7%E5%8B%95">コンテナ起動</a></h2> <pre><code>$ kubectl run hello-minikube --image=k8s.gcr.io/echoserver:1.4 --port=8080 </code></pre> <p>k8s.gcr.io/echoserver:1.4のイメージを使って8080ポートでhello-minikubeというコンテナを起動する。</p> <h2 id="podの状態確認"><a href="#pod%E3%81%AE%E7%8A%B6%E6%85%8B%E7%A2%BA%E8%AA%8D">podの状態確認</a></h2> <pre><code>$ kubectl get pod NAME READY STATUS RESTARTS AGE hello-minikube-78c9fc5f89-x7m9g 1/1 Running 0 1m </code></pre> <h2 id="deploymentの状態確認"><a href="#deployment%E3%81%AE%E7%8A%B6%E6%85%8B%E7%A2%BA%E8%AA%8D">deploymentの状態確認</a></h2> <pre><code>$ kubectl get deployment NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE hello-minikube 1 1 1 1 1m </code></pre> <h2 id="コンテナを外部に公開"><a href="#%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E3%82%92%E5%A4%96%E9%83%A8%E3%81%AB%E5%85%AC%E9%96%8B">コンテナを外部に公開</a></h2> <pre><code>$ kubectl expose deployment hello-minikube --type=NodePort </code></pre> <p>hello-minikubeというコンテナをNodePortを使って外部に公開します。</p> <h2 id="サービスの削除・deploymentの削除"><a href="#%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E3%81%AE%E5%89%8A%E9%99%A4%E3%83%BBdeployment%E3%81%AE%E5%89%8A%E9%99%A4">サービスの削除・deploymentの削除</a></h2> <pre><code>$ kubectl delete service hello-node $ kubectl delete deployment hello-node </code></pre> <h2 id="minikubeの仮想マシン(VM)を停止:"><a href="#minikube%E3%81%AE%E4%BB%AE%E6%83%B3%E3%83%9E%E3%82%B7%E3%83%B3%28VM%29%E3%82%92%E5%81%9C%E6%AD%A2%3A">minikubeの仮想マシン(VM)を停止:</a></h2> <pre><code>$ minikube stop </code></pre> <h2 id="minikubeのVMを削除"><a href="#minikube%E3%81%AEVM%E3%82%92%E5%89%8A%E9%99%A4">minikubeのVMを削除</a></h2> <pre><code>$ minikube delete </code></pre> <h2 id="(番外編)minikubeのdashboardを見る"><a href="#%28%E7%95%AA%E5%A4%96%E7%B7%A8%29minikube%E3%81%AEdashboard%E3%82%92%E8%A6%8B%E3%82%8B">(番外編)minikubeのdashboardを見る</a></h2> <pre><code>$ minikube dashboard </code></pre> <p><a href="https://crieit.now.sh/upload_images/3c94d8c0d18fa9ffa37d49f02fe946c55d0cf4ea76674.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/3c94d8c0d18fa9ffa37d49f02fe946c55d0cf4ea76674.png?mw=700" alt="image" /></a></p> <h1 id="参考リンク"><a href="#%E5%8F%82%E8%80%83%E3%83%AA%E3%83%B3%E3%82%AF">参考リンク</a></h1> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://knowledge.sakura.ad.jp/15320/">簡単にローカルKubernetes環境を構築できるツール「Minikube」</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://dev.classmethod.jp/cloud/minikube/">Minikubeを使ってローカル環境にKubernetes環境を用意する<br /> </a></li> </ul> ckoshien