Kubernetesドキュメント
Learn Kubernetes using Interactive Browser-Based Scenarios
- https://www.katacoda.com/courses/kubernetes/
- フリーで使えるMinikubeの実習環境
Kubernetes道場 Advent Calendar 2018
今こそ始めよう! Kubernetes入門
コンテナを利用したHTML動作確認用のテストWebサーバ
はじめに
静的なHTMLファイルの動作確認は、基本的にはローカルに保存した.htmlファイルをブラウザに読み込ませればよい。 ただし、XMLHttpRequestやFetch APIを利用した非同期通信を行っている場合は、テスト用のWebサーバを準備しないとテストできない。 そのため、コンテナを利用してテスト用のWebサーバを立ち上げることにした。
環境
# cat /etc/os-release | grep PRETTY_NAME PRETTY_NAME="Ubuntu 20.04.1 LTS" # docker --version Docker version 19.03.13, build 4484c46d9d
テスト用Webサーバの起動と停止
初回の起動は以下のコマンドを実行する。
/path/to/src
は環境によって変えること。
# docker run --name test-web-server -v /path/to/src/:/usr/share/nginx/html:ro -d -p 8080:80 nginx
停止は以下のコマンドを実行する。
# docker stop test-web-server
もう一度起動するには、以下を実行するか、
# docker start test-web-server
もしくはコンテナを削除してから、初回の起動と同じコマンドを実行する。
# docker rm test-web-server # docker run --name test-web-server -v /path/to/src/:/usr/share/nginx/html:ro -d -p 8080:80 nginx
参考
Docker run reference
Docker start reference
Docker stop reference
Docker rm reference
Nginx - Docker Hub
Ubuntu 20.04LTSでMinikubeを構築する
- はじめに
- (1) CPUの仮想化テクノロジーのサポートの確認
- (2) kubectlのインストール
- (3) 仮想化基盤の構築
- (4) Minikubeのインストール
- (5) 動作確認
- (6) おまけ - 環境のクリア
- 参考
はじめに
Minikubeのマニュアルを読みながら、Ubuntu 20.04LTSでMinikubeを構築したときのメモ。 マニュアルの中身だが、Linuxディストリビューションや仮想化基盤などでいくらか分岐があるので、忘れた頃に読み直すと時間がかかる。 今後のMinikubeの再構築を効率的に行うために、ここでは自分の環境に合わせて一本道になるように、手順を残しておく。
(1) CPUの仮想化テクノロジーのサポートの確認
以下を実行して、何かしら表示が出ればOK。
# grep -E --color 'vmx|svm' /proc/cpuinfo flags : fpu vme de pse tsc msr pae mce cx8 (以降省略)
何も表示されない場合は、BIOSで仮想化テクノロジーを有効化するなどの対処が必要になる。
(2) kubectlのインストール
Ubuntu 20.04LTSだとSnapを使うのが一番簡単。
# sudo snap install kubectl --classic
kubectlの動作確認をしておく。
# kubectl version --client Client Version: version.Info{Major:"1", Minor:"19", (以降省略)
(3) 仮想化基盤の構築
ここではKVMを利用することにする。 他の選択肢としては、VirtualBoxやDockerがある。 KVMの構築については以下のブログを参照。
(4) Minikubeのインストール
インストール方法は、単にシングルバイナリをコピーする方法と、各種パッケージ(.debなど)を利用した方法がある。 ただし、執筆時点(2020/10)ではパッケージを利用する方法はまだExperimentalと注意書きがあるので、今回はシングルバイナリを利用する。
# curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 # sudo install minikube /usr/local/bin
(5) 動作確認
(5-1) Minikubeの起動
以下のコマンドを実行すると、(必要なら)ファイルが自動的にダウンロードされて、環境が構築される。
# minikube start --driver=kvm2 😄 Ubuntu 20.04 上の minikube v1.13.1 ✨ 設定を元に、 kvm2 ドライバを使用します 💾 docker-machine-driver-kvm2 ドライバをダウンロードしています: > docker-machine-driver-kvm2.sha256: 65 B / 65 B [-------] 100.00% ? p/s 0s > docker-machine-driver-kvm2: 13.81 MiB / 13.81 MiB 100.00% 359.38 KiB p/s 💿 VM ブートイメージをダウンロードしています... > minikube-v1.13.1.iso.sha256: 65 B / 65 B [-------------] 100.00% ? p/s 0s > minikube-v1.13.1.iso: 173.91 MiB / 173.91 MiB 100.00% 209.31 KiB p/s 14m 👍 コントロールプレーンのノード minikube を minikube 上で起動しています 💾 Kubernetes v1.19.2 のダウンロードの準備をしています > preloaded-images-k8s-v6-v1.19.2-docker-overlay2-amd64.tar.lz4: 486.36 MiB 🔥 kvm2 VM (CPUs=2, Memory=3900MB, Disk=20000MB) を作成しています... 🐳 Docker 19.03.12 で Kubernetes v1.19.2 を準備しています... 🔎 Kubernetes コンポーネントを検証しています... 🌟 有効なアドオン: default-storageclass, storage-provisioner 🏄 Done! kubectl is now configured to use "minikube" by default
(5-2) Minikubeの状態の確認
以下のコマンドを実行して、Minikubeの状態を確認する。
# minikube status minikube type: Control Plane host: Running kubelet: Running apiserver: Running kubeconfig: Configured
ついでに、VMのリストを表示してみる。
# virsh list Id Name State --------------------------- 1 minikube running
(5-3) Minikubeの停止
# minikube stop ✋ ノード "minikube" を停止しています... 🛑 1台のノードが停止しました。
(6) おまけ - 環境のクリア
以下のコマンドを実行することで、環境はまっさらになるはず。
minikube delete --all --purge 🔥 kvm2 の「minikube」を削除しています... 💀 クラスタ "minikube" の全てのトレースを削除しました。 🔥 Successfully deleted all profiles 💀 Successfully purged minikube directory located at - [/home/jaybanuan/.minikube]
参考
Kubernetes Documentation > Tasks > Install Tools > Install Minikube
Kubernetes Documentation > Tasks > Install Tools > Install and Set Up kubectl
REST APIで見かけるvnd.を含んでいるメディアタイプについて
はじめに
REST APIで時々見かけるメディアタイプで、vnd.
を含んでいるものがある。
これが何なのかが気になったので調べた。
vnd.
はベンダ固有のメディアタイプ
RFC 6838: Media Type Specifications and Registration Procedures によると、vnd.
はベンダーの裁量で決めた独自のサブタイプにつけるプレフィックスらしい。
RFC 6838では、このプレフィックスのことをfacetと呼んでるが、文脈からして名前空間に相当する概念と理解した。
サブタイプがvnd.
をから始まっていても、なかにはIANAに公式に登録されているメディアタイプもある。
具体例
GitHubのAPIだとapplication/vnd.github+json
というメディアタイプが利用されている。
参考
RFC 6838 > 3.2. Vendor Tree
Media Types
- https://www.iana.org/assignments/media-types/media-types.xhtml
- 公式に登録されているメディアタイプで、なかには
vnd.
を含むものもある
GitHubDocs > REST API > Overview > Media types
Ansibleでの環境変数の設定(/etc/environment)が挙動不審
はじめに
AnsibleのPlaybookで/etc/environment
にプロキシ関連の環境変数(http_proxy
とか)を書き込んだ際、書き込んだはずの環境変数が後続のタスクで参照できなかったので調査した。
環境
$ cat /etc/os-release | grep PRETTY_NAME PRETTY_NAME="Ubuntu 20.04.1 LTS" $ ansible --version ansible 2.9.7 config file = None configured module search path = ['/home/redj/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules'] ansible python module location = /home/redj/.local/lib/python3.8/site-packages/ansible executable location = /home/redj/.local/bin/ansible python version = 3.8.2 (default, Jul 16 2020, 14:00:26) [GCC 9.3.0]
現象
試行 1 - 環境変数が見えない
以下のPlaybookを実行すると、最後のタスクdebug
でhttp_proxy
などが表示されてほしいが、実際には表示されない。
- hosts: target tasks: - name: /etc/environment にプロキシの環境変数を書き込み become: yes ini_file: path: /etc/environment no_extra_spaces: yes section: null option: "{{ item.key }}" value: "{{ item.value }}" loop: "{{ proxy_envs | dict2items }}" vars: proxy_envs: http_proxy: http://192.168.8.8:3128/ https_proxy: http://192.168.8.8:3128/ no_proxy: 127.0.0.1,localhost - name: 環境変数の取得 shell: env | grep "_proxy" | cat register: result - name: 環境変数の表示 debug: var: result.stdout_lines
実行結果は以下のようになり、プロキシ関連の環境変数が見つからないことがわかる。
$ ansible-playbook -i hosts.yml playbook.yml PLAY [target] ********************************************************************************************************************** TASK [Gathering Facts] ************************************************************************************************************* ok: [192.168.8.16] TASK [/etc/environment にプロキシの環境変数を書き込み] ******************************************************************************************** changed: [192.168.8.16] => (item={'key': 'http_proxy', 'value': 'http://192.168.8.8:3128/'}) changed: [192.168.8.16] => (item={'key': 'https_proxy', 'value': 'http://192.168.8.8:3128/'}) changed: [192.168.8.16] => (item={'key': 'no_proxy', 'value': '127.0.0.1,localhost'}) TASK [環境変数の取得] ********************************************************************************************************************* changed: [192.168.8.16] TASK [環境変数の表示] ********************************************************************************************************************* ok: [192.168.8.16] => { "result.stdout_lines": [] } PLAY RECAP ************************************************************************************************************************* 192.168.8.16 : ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
試行 2 - 環境変数が見える
試しにもう一度実行してみると、今回は環境変数は見えている。
/etc/environment
の更新がok
になっていることから、初回の実行での環境変数の追加は成功していることが分かる。
なぜ初回の実行では環境変数が見えていないんだろうか…。
$ ansible-playbook -i hosts.yml playbook.yml PLAY [target] ********************************************************************************************************************** TASK [Gathering Facts] ************************************************************************************************************* ok: [192.168.8.16] TASK [/etc/environment にプロキシの環境変数を書き込み] ******************************************************************************************** ok: [192.168.8.16] => (item={'key': 'http_proxy', 'value': 'http://192.168.8.8:3128/'}) ok: [192.168.8.16] => (item={'key': 'https_proxy', 'value': 'http://192.168.8.8:3128/'}) ok: [192.168.8.16] => (item={'key': 'no_proxy', 'value': '127.0.0.1,localhost'}) TASK [環境変数の取得] ********************************************************************************************************************* changed: [192.168.8.16] TASK [環境変数の表示] ********************************************************************************************************************* ok: [192.168.8.16] => { "result.stdout_lines": [ "no_proxy=127.0.0.1,localhost", "https_proxy=http://192.168.8.8:3128/", "http_proxy=http://192.168.8.8:3128/" ] } PLAY RECAP ************************************************************************************************************************* 192.168.8.16 : ok=4 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
試行 3 - 環境変数が見える
今度はターゲットのサーバの/etc/environment
を元に戻してやり直してみる。
さらに、Playbookでbecome: yes
の位置を以下のようにタスク全体にかかるように移動しておく。
- hosts: target become: yes tasks: (以下略)
このPlaybookを実行すると、今度は初回の実行で環境変数が見つかる。
/etc/environment
の更新がchanged
になっていることから、環境変数の追加が成功し、かつ後続のタスクで環境変数が見えていることが分かる。
なぜだ…。
$ ansible-playbook -i hosts.yml playbook.yml PLAY [target] ********************************************************************************************************************** TASK [Gathering Facts] ************************************************************************************************************* ok: [192.168.8.16] TASK [/etc/environment にプロキシの環境変数を書き込み] ******************************************************************************************** changed: [192.168.8.16] => (item={'key': 'http_proxy', 'value': 'http://192.168.8.8:3128/'}) changed: [192.168.8.16] => (item={'key': 'https_proxy', 'value': 'http://192.168.8.8:3128/'}) changed: [192.168.8.16] => (item={'key': 'no_proxy', 'value': '127.0.0.1,localhost'}) TASK [環境変数の取得] ********************************************************************************************************************* changed: [192.168.8.16] TASK [環境変数の表示] ********************************************************************************************************************* ok: [192.168.8.16] => { "result.stdout_lines": [ "no_proxy=127.0.0.1,localhost", "https_proxy=http://192.168.8.8:3128/", "http_proxy=http://192.168.8.8:3128/" ] } PLAY RECAP ************************************************************************************************************************* 192.168.8.16 : ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
解決方法
結論から言うと、Ansibleが呼び出すsshコマンドのパラメータを調整して、Multiplexing (多重化)を無効化することで解決した。
SSHのMultiplexingとは、ひとつのTCPコネクション上に複数のSSHセッションをのせる仕組みのこと。 言い換えるとコネクションを再利用する仕組みであり、これを利用すると都度接続が不要になため、sshコマンドを連発するような場合に高速化が見込める。
つまりこれはAnsibleに適した高速化の仕組みであり、ANSIBLE_SSH_ARGS
という設定項目でデフォルトで有効化されている。
以下にマニュアルでのANSIBLE_SSH_ARGS
の説明を抜粋する。
項目 | 説明 |
---|---|
Description: | If set, this will override the Ansible default ssh arguments. In particular, users may wish to raise the ControlPersist time to encourage performance. A value of 30 minutes may be appropriate. Be aware that if -o ControlPath is set in ssh_args, the control path setting is not used. |
Default: | -C -o ControlMaster=auto -o ControlPersist=60s |
Ini Section: | ssh_connection |
Ini Key: | ssh_args |
Environment: | ANSIBLE_SSH_ARGS |
Multiplexingを無効化するsshのパラメータは?
sshのMultiplexingに関係するパラメータは、主に以下の3つ。 「簡単な説明」は自分なりにまとめたものなので、正確な定義はOpenSSHのマニュアルを参照のこと。
パラメータ | 簡単な説明 |
---|---|
ControlMaster | yes の場合は自身がMasterであることを、no の場合はMasterではない(=クライアントである)ことを示す。auto の場合はMasterがいない時には自動的に自身がMasterになる。 |
ControlPersist | クライアントがいなくなってからMasterのコネクションを切断するまでのタイムアウト値。 |
ControlPath | コネクションを共有するためのソケットファイルのパス。none を指定した場合はMultiplexingを利用しない。 |
上の表より、sshのコマンドラインパラメータとして-o ControlPath=none
を付け加えれば良い。
注意点として、ググると「Multiplexingをオフにするには-o ControlMaster=no
としておけ」みたいな情報があるが、これは「自分はクライアント」と宣言しているのであり、オフになったわけではない。
Ansibleでの設定方法 1 - ANSIBLE_SSH_ARGS
sshのパラメータの「ベース」を指定するANSIBLE_SSH_ARGS
に対して-C -o ControlPath=none
を設定する。
ANSIBLE_SSH_ARGS
の設定方法は、ansible.cfg
で設定する方法と、環境変数で設定する方法の、2パターンある。
ansible.cfg
で設定する場合は、以下のようにする。
[ssh_connection] ssh_args=-C -o ControlPath=none
また、環境変数で設定するには、Ansibleを以下のように実行するか、あるいは~/.profile
などに当該の環境変数を定義しておく。
$ export ANSIBLE_SSH_ARGS="-C -o ControlPath=none" $ ansible-playbook playbook.yml
Ansibleでの設定方法 2 - ansible_ssh_extra_args
ansible_ssh_extra_args
で指定したsshのパラメータは、ANSIBLE_SSH_ARGS
の内容の後ろに追加されてsshに渡される。
ansible_ssh_extra_args
の設定方法は、Ansibleのコマンドラインパラメータとして設定する方法と、インベントリなどでAnsibleの変数として設定する方法の、2パターンある。
Ansibleのコマンドラインパラメータとして設定する場合は、以下のようにAnsibleを実行する。
$ ansible-playbook --ssh-extra-args="-o ControlPath=none" -i hosts.yml playbook
インベントリでAnsibleの変数として設定するには、インベントリを以下のように記述する。
devpc: hosts: "192.168.8.16": ansible_user: jaybanuan ansible_ssh_extra_args: -o ControlPath=none
Ansibleでの設定方法 - まとめ
Ansibleでのsshのコマンドラインパラメータの指定場所がややこしいので、以下の表にまとめておく。
個人的には、ansible_ssh_extra_args
をAnsibleの変数としてインベントリで定義すると、接続先に柔軟に対応できるためよいと思う。
設定場所 | ANSIBLE_SSH_ARGS | ansible_ssh_extra_args |
---|---|---|
ansible.cfg | レ | |
起動時のパラメータ | レ | |
環境変数 | レ | |
Ansibleの変数 | レ |
結局のところ原因は何?
結局はsshのMultiplexingが影響しているという事以外は分からなかった。
sshのMultiplexingに辿り着いたのは、/etc/environment
はログインしなおせば効くはずなのに効いておらず、Multiplexingはクライアントではsshの認証が省略される(のか?)ので、ログアウトしきれていないのでは、と推測したため。