CentOS7でKubeadmを使用してKubernetesクラスターを作成する方法
著者は、 Write for DOnations プログラムの一環として、 Free and Open SourceFundを選択して寄付を受け取りました。
序章
Kubernetes は、コンテナーを大規模に管理するコンテナーオーケストレーションシステムです。 Kubernetesは、本番環境でコンテナを実行した経験に基づいてGoogleが最初に開発したもので、オープンソースであり、世界中のコミュニティによって積極的に開発されています。
注:このチュートリアルでは、この記事の公開時点でサポートされている公式バージョンであるバージョン1.14のKubernetesを使用しています。 最新バージョンの最新情報については、Kubernetesの公式ドキュメントの最新リリースノートを参照してください。
Kubeadm は、APIサーバー、コントローラーマネージャー、KubeDNSなどのKubernetesコンポーネントのインストールと構成を自動化します。 ただし、ユーザーを作成したり、オペレーティングシステムレベルの依存関係のインストールとその構成を処理したりすることはありません。 これらの予備的なタスクには、AnsibleやSaltStackなどの構成管理ツールを使用できます。 これらのツールを使用すると、追加のクラスターの作成や既存のクラスターの再作成がはるかに簡単になり、エラーが発生しにくくなります。
このガイドでは、AnsibleとKubeadmを使用してKubernetesクラスターを最初からセットアップし、コンテナー化されたNginxアプリケーションをデプロイします。
目標
クラスタには、次の物理リソースが含まれます。
1つのマスターノード
マスターノード(Kubernetesの node はサーバーを指します)は、クラスターの状態を管理する責任があります。 Etcd を実行し、ワーカーノードへのワークロードをスケジュールするコンポーネント間でクラスターデータを格納します。
2つのワーカーノード
ワーカーノードは、ワークロード(つまり コンテナ化されたアプリケーションとサービス)が実行されます。 ワーカーは、割り当てられた後もワークロードを実行し続けます。スケジュールが完了するとマスターがダウンした場合でも同様です。 ワーカーを追加することで、クラスターの容量を増やすことができます。
このガイドを完了すると、クラスター内のサーバーにアプリケーションが消費するのに十分なCPUおよびRAMリソースがあれば、コンテナー化されたアプリケーションを実行する準備が整います。 Webアプリケーション、データベース、デーモン、コマンドラインツールなど、ほとんどすべての従来のUnixアプリケーションをコンテナ化して、クラスタで実行することができます。 クラスタ自体は、各ノードで約300〜500MBのメモリと10% ofのCPUを消費します。
クラスターをセットアップしたら、Webサーバー Nginx をクラスターにデプロイして、ワークロードが正しく実行されていることを確認します。
前提条件
- ローカルのLinux/macOS/BSDマシン上のSSHキーペア。 これまでにSSHキーを使用したことがない場合は、ローカルマシンでのSSHキーの設定方法の説明に従って、SSHキーの設定方法を学ぶことができます。
- それぞれ少なくとも2GBのRAMと2つのvCPUを備えたCentOS7を実行している3台のサーバー。 SSHキーペアを使用してrootユーザーとして各サーバーにSSHで接続できる必要があります。 マスターノードのcentosユーザーのアカウントにも公開鍵を追加してください。 特定のユーザーアカウントにSSHキーを追加するためのガイダンスが必要な場合は、CentOS7でSSHキーを設定する方法に関するこのチュートリアルを参照してください。
- Ansibleがローカルマシンにインストールされています。 インストール手順については、公式のAnsibleインストールドキュメントに従ってください。
- Ansibleプレイブックに精通していること。 レビューについては、 Configuration Management 101:Writing AnsiblePlaybooksをご覧ください。
- Dockerイメージからコンテナーを起動する方法に関する知識。 復習が必要な場合は、 CentOS 7にDockerをインストールして使用する方法の「ステップ5—Dockerコンテナの実行」を参照してください。
ステップ1—ワークスペースディレクトリとAnsibleインベントリファイルを設定する
このセクションでは、ワークスペースとして機能するディレクトリをローカルマシンに作成します。 また、Ansibleをローカルで構成して、リモートサーバーと通信してコマンドを実行できるようにします。 これを行うには、サーバーのIPアドレスや各サーバーが属するグループなどのインベントリ情報を含むhosts
ファイルを作成します。
3台のサーバーのうち、1台はmaster_ip
と表示されたIPを持つマスターになります。 他の2つのサーバーはワーカーであり、IPworker_1_ip
とworker_2_ip
を持ちます。
ローカルマシンのホームディレクトリに~/kube-cluster
という名前のディレクトリを作成し、その中にcd
を作成します。
mkdir ~/kube-cluster cd ~/kube-cluster
このディレクトリは、チュートリアルの残りの部分のワークスペースになり、すべてのAnsibleプレイブックが含まれます。 また、すべてのローカルコマンドを実行するディレクトリにもなります。
vi
またはお気に入りのテキストエディタを使用して、~/kube-cluster/hosts
という名前のファイルを作成します。
vi ~/kube-cluster/hosts
i
を押して、次のテキストをファイルに挿入します。これにより、クラスターの論理構造に関する情報が指定されます。
〜/ kube-cluster / hosts
[masters] master ansible_host=master_ip ansible_user=root [workers] worker1 ansible_host=worker_1_ip ansible_user=root worker2 ansible_host=worker_2_ip ansible_user=root
終了したら、ESC
を押してから:wq
を押してファイルに変更を書き込み、終了します。
Ansibleのインベントリファイルは、コマンドを実行するための単一のユニットとしてターゲットとするIPアドレス、リモートユーザー、サーバーのグループなどのサーバー情報を指定するために使用されることを思い出してください。 ~/kube-cluster/hosts
がインベントリファイルになり、クラスターの論理構造を指定する2つのAnsibleグループ(mastersとworkers)を追加しました。
masters グループには、マスターノードのIP(master_ip
)を一覧表示し、Ansibleがrootユーザーとしてリモートコマンドを実行するように指定する「master」という名前のサーバーエントリがあります。
同様に、 workers グループには、ansible_user
をルートとして指定するワーカーサーバー用の2つのエントリ(worker_1_ip
とworker_2_ip
)があります。
グループを使用してサーバーインベントリを設定したら、オペレーティングシステムレベルの依存関係のインストールと構成設定の作成に進みましょう。
ステップ2—Kubernetesの依存関係をインストールする
このセクションでは、CentOSのyum
パッケージマネージャーを使用して、Kubernetesに必要なオペレーティングシステムレベルのパッケージをインストールします。 これらのパッケージは次のとおりです。
- Docker-コンテナランタイム。 これは、コンテナを実行するコンポーネントです。 rkt などの他のランタイムのサポートは、Kubernetesで活発に開発されています。
kubeadm
-クラスターのさまざまなコンポーネントを標準的な方法でインストールおよび構成するCLIツール。kubelet
-すべてのノードで実行され、ノードレベルの操作を処理するシステムサービス/プログラム。kubectl
-APIサーバーを介してクラスターにコマンドを発行するために使用されるCLIツール。
ワークスペースに~/kube-cluster/kube-dependencies.yml
という名前のファイルを作成します。
vi ~/kube-cluster/kube-dependencies.yml
次の再生をファイルに追加して、これらのパッケージをサーバーにインストールします。
〜/ kube-cluster / kube-dependencies.yml
- hosts: all become: yes tasks: - name: install Docker yum: name: docker state: present update_cache: true - name: start Docker service: name: docker state: started - name: disable SELinux command: setenforce 0 - name: disable SELinux on reboot selinux: state: disabled - name: ensure net.bridge.bridge-nf-call-ip6tables is set to 1 sysctl: name: net.bridge.bridge-nf-call-ip6tables value: 1 state: present - name: ensure net.bridge.bridge-nf-call-iptables is set to 1 sysctl: name: net.bridge.bridge-nf-call-iptables value: 1 state: present - name: add Kubernetes' YUM repository yum_repository: name: Kubernetes description: Kubernetes YUM repository baseurl: https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64 gpgkey: https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg gpgcheck: yes - name: install kubelet yum: name: kubelet-1.14.0 state: present update_cache: true - name: install kubeadm yum: name: kubeadm-1.14.0 state: present - name: start kubelet service: name: kubelet enabled: yes state: started - hosts: master become: yes tasks: - name: install kubectl yum: name: kubectl-1.14.0 state: present allow_downgrade: yes
プレイブックの最初のプレイは次のことを行います。
- コンテナランタイムであるDockerをインストールします。
- Dockerサービスを開始します。
- まだKubernetesで完全にサポートされていないため、SELinuxを無効にします。
- ネットワーキングに必要ないくつかのnetfilter関連の
sysctl
値を設定します。 これにより、KubernetesはノードでブリッジされたIPv4およびIPv6ネットワークトラフィックを受信するためのiptablesルールを設定できます。 - KubernetesYUMリポジトリをリモートサーバーのリポジトリリストに追加します。
kubelet
およびkubeadm
をインストールします。
2番目のプレイは、マスターノードにkubectl
をインストールする単一のタスクで構成されます。
注: Kubernetesのドキュメントでは、ご使用の環境に最新の安定したリリースのKubernetesを使用することを推奨していますが、このチュートリアルでは特定のバージョンを使用しています。 これにより、Kubernetesは急速に変化し、最新バージョンがこのチュートリアルで機能しない可能性があるため、手順を正常に実行できるようになります。
終了したら、ファイルを保存して閉じます。
次に、プレイブックを実行します。
ansible-playbook -i hosts ~/kube-cluster/kube-dependencies.yml
完了すると、次のような出力が表示されます。
OutputPLAY [all] **** TASK [Gathering Facts] **** ok: [worker1] ok: [worker2] ok: [master] TASK [install Docker] **** changed: [master] changed: [worker1] changed: [worker2] TASK [disable SELinux] **** changed: [master] changed: [worker1] changed: [worker2] TASK [disable SELinux on reboot] **** changed: [master] changed: [worker1] changed: [worker2] TASK [ensure net.bridge.bridge-nf-call-ip6tables is set to 1] **** changed: [master] changed: [worker1] changed: [worker2] TASK [ensure net.bridge.bridge-nf-call-iptables is set to 1] **** changed: [master] changed: [worker1] changed: [worker2] TASK [start Docker] **** changed: [master] changed: [worker1] changed: [worker2] TASK [add Kubernetes' YUM repository] ***** changed: [master] changed: [worker1] changed: [worker2] TASK [install kubelet] ***** changed: [master] changed: [worker1] changed: [worker2] TASK [install kubeadm] ***** changed: [master] changed: [worker1] changed: [worker2] TASK [start kubelet] **** changed: [master] changed: [worker1] changed: [worker2] PLAY [master] ***** TASK [Gathering Facts] ***** ok: [master] TASK [install kubectl] ****** ok: [master] PLAY RECAP **** master : ok=9 changed=5 unreachable=0 failed=0 worker1 : ok=7 changed=5 unreachable=0 failed=0 worker2 : ok=7 changed=5 unreachable=0 failed=0
実行後、Docker、kubeadm
、およびkubelet
がすべてのリモートサーバーにインストールされます。 kubectl
は必須コンポーネントではなく、クラスターコマンドの実行にのみ必要です。 kubectl
コマンドはマスターからのみ実行するため、このコンテキストではマスターノードにのみインストールするのが理にかなっています。 ただし、kubectl
コマンドは、任意のワーカーノードから、またはクラスターを指すようにインストールおよび構成できる任意のマシンから実行できることに注意してください。
これで、すべてのシステム依存関係がインストールされました。 マスターノードを設定し、クラスターを初期化してみましょう。
ステップ4—マスターノードのセットアップ
このセクションでは、マスターノードを設定します。 ただし、プレイブックを作成する前に、クラスターに両方が含まれるため、ポッドやポッドネットワークプラグインなどのいくつかの概念を説明する価値があります。
ポッドは、1つ以上のコンテナを実行するアトミックユニットです。 これらのコンテナは、ファイルボリュームやネットワークインターフェイスなどのリソースを共有します。 ポッドはKubernetesのスケジューリングの基本単位です。ポッド内のすべてのコンテナは、ポッドがスケジュールされているのと同じノードで実行されることが保証されています。
各ポッドには独自のIPアドレスがあり、あるノードのポッドは、ポッドのIPを使用して別のノードのポッドにアクセスできる必要があります。 単一ノード上のコンテナは、ローカルインターフェイスを介して簡単に通信できます。 ただし、ポッド間の通信はより複雑であり、あるノードのポッドから別のノードのポッドにトラフィックを透過的にルーティングできる別個のネットワークコンポーネントが必要です。
この機能は、ポッドネットワークプラグインによって提供されます。 このクラスターでは、安定したパフォーマンスの高いオプションであるフランネルを使用します。
ローカルマシンでmaster.yml
という名前のAnsibleプレイブックを作成します。
vi ~/kube-cluster/master.yml
次のプレイをファイルに追加して、クラスターを初期化し、Flannelをインストールします。
〜/ kube-cluster / master.yml
- hosts: master become: yes tasks: - name: initialize the cluster shell: kubeadm init --pod-network-cidr=10.244.0.0/16 >> cluster_initialized.txt args: chdir: $HOME creates: cluster_initialized.txt - name: create .kube directory become: yes become_user: centos file: path: $HOME/.kube state: directory mode: 0755 - name: copy admin.conf to user's kube config copy: src: /etc/kubernetes/admin.conf dest: /home/centos/.kube/config remote_src: yes owner: centos - name: install Pod network become: yes become_user: centos shell: kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/a70459be0084506e4ec919aa1c114638878db11b/Documentation/kube-flannel.yml >> pod_network_setup.txt args: chdir: $HOME creates: pod_network_setup.txt
このプレイの内訳は次のとおりです。
- 最初のタスクは、
kubeadm init
を実行してクラスターを初期化します。 引数--pod-network-cidr=10.244.0.0/16
を渡すと、ポッドIPが割り当てられるプライベートサブネットが指定されます。 Flannelは、デフォルトで上記のサブネットを使用します。kubeadm
に同じサブネットを使用するように指示しています。 - 2番目のタスクは、
/home/centos
に.kube
ディレクトリを作成します。 このディレクトリには、クラスタへの接続に必要な管理キーファイルやクラスタのAPIアドレスなどの構成情報が保持されます。 - 3番目のタスクは、
kubeadm init
から生成された/etc/kubernetes/admin.conf
ファイルを非ルートcentosユーザーのホームディレクトリにコピーします。 これにより、kubectl
を使用して、新しく作成されたクラスターにアクセスできるようになります。 - 最後のタスクは
kubectl apply
を実行して、Flannel
をインストールします。kubectl apply -f descriptor.[yml|json]
は、kubectl
にdescriptor.[yml|json]
ファイルに記述されているオブジェクトを作成するように指示するための構文です。kube-flannel.yml
ファイルには、クラスターでFlannel
をセットアップするために必要なオブジェクトの説明が含まれています。
終了したら、ファイルを保存して閉じます。
プレイブックを実行します。
ansible-playbook -i hosts ~/kube-cluster/master.yml
完了すると、次のような出力が表示されます。
Output PLAY [master] **** TASK [Gathering Facts] **** ok: [master] TASK [initialize the cluster] **** changed: [master] TASK [create .kube directory] **** changed: [master] TASK [copy admin.conf to user's kube config] ***** changed: [master] TASK [install Pod network] ***** changed: [master] PLAY RECAP **** master : ok=5 changed=4 unreachable=0 failed=0
マスターノードのステータスを確認するには、次のコマンドを使用してマスターノードにSSHで接続します。
ssh centos@master_ip
マスターノード内に入ったら、次を実行します。
kubectl get nodes
次の出力が表示されます。
OutputNAME STATUS ROLES AGE VERSION master Ready master 1d v1.14.0
出力は、master
ノードがすべての初期化タスクを完了し、Ready
状態にあり、そこからワーカーノードの受け入れとAPIサーバーに送信されたタスクの実行を開始できることを示します。 これで、ローカルマシンからワーカーを追加できます。
ステップ5—ワーカーノードを設定する
クラスタにワーカーを追加するには、それぞれに対して1つのコマンドを実行する必要があります。 このコマンドには、マスターのAPIサーバーのIPアドレスやポート、セキュアトークンなどの必要なクラスター情報が含まれています。 セキュアトークンを渡すノードのみがクラスターに参加できます。
ワークスペースに戻り、workers.yml
という名前のプレイブックを作成します。
vi ~/kube-cluster/workers.yml
次のテキストをファイルに追加して、ワーカーをクラスターに追加します。
〜/ kube-cluster / workers.yml
- hosts: master become: yes gather_facts: false tasks: - name: get join command shell: kubeadm token create --print-join-command register: join_command_raw - name: set join command set_fact: join_command: "{{ join_command_raw.stdout_lines[0] }}" - hosts: workers become: yes tasks: - name: join cluster shell: "{{ hostvars['master'].join_command }} --ignore-preflight-errors all >> node_joined.txt" args: chdir: $HOME creates: node_joined.txt
プレイブックの機能は次のとおりです。
- 最初のプレイでは、ワーカーノードで実行する必要のあるjoinコマンドを取得します。 このコマンドは次の形式になります:
kubeadm join --token <token> <master-ip>:<master-port> --discovery-token-ca-cert-hash sha256:<hash>
。 適切なトークンおよびハッシュ値を持つ実際のコマンドを取得すると、タスクはそれをファクトとして設定し、次のプレイがその情報にアクセスできるようにします。 - 2番目のプレイには、すべてのワーカーノードでjoinコマンドを実行する単一のタスクがあります。 このタスクが完了すると、2つのワーカーノードがクラスターの一部になります。
終了したら、ファイルを保存して閉じます。
プレイブックを実行します。
ansible-playbook -i hosts ~/kube-cluster/workers.yml
完了すると、次のような出力が表示されます。
OutputPLAY [master] **** TASK [get join command] **** changed: [master] TASK [set join command] ***** ok: [master] PLAY [workers] ***** TASK [Gathering Facts] ***** ok: [worker1] ok: [worker2] TASK [join cluster] ***** changed: [worker1] changed: [worker2] PLAY RECAP ***** master : ok=2 changed=1 unreachable=0 failed=0 worker1 : ok=2 changed=1 unreachable=0 failed=0 worker2 : ok=2 changed=1 unreachable=0 failed=0
ワーカーノードが追加されたことで、クラスターが完全にセットアップされて機能し、ワーカーがワークロードを実行できるようになりました。 アプリケーションをスケジュールする前に、クラスターが意図したとおりに機能していることを確認しましょう。
ステップ6—クラスターの検証
ノードがダウンしているか、マスターとワーカー間のネットワーク接続が正しく機能していないために、セットアップ中にクラスターが失敗することがあります。 クラスタを検証し、ノードが正しく動作していることを確認しましょう。
マスターノードからクラスターの現在の状態をチェックして、ノードの準備ができていることを確認する必要があります。 マスターノードから切断した場合は、次のコマンドを使用してマスターノードにSSHで戻すことができます。
ssh centos@master_ip
次に、次のコマンドを実行して、クラスターのステータスを取得します。
kubectl get nodes
次のような出力が表示されます。
OutputNAME STATUS ROLES AGE VERSION master Ready master 1d v1.14.0 worker1 Ready <none> 1d v1.14.0 worker2 Ready <none> 1d v1.14.0
すべてのノードの値がSTATUS
に対してReady
である場合、それらはクラスターの一部であり、ワークロードを実行する準備ができていることを意味します。
ただし、一部のノードにNotReady
がSTATUS
として含まれている場合は、ワーカーノードがまだセットアップを完了していない可能性があります。 kubectl get node
を再実行して新しい出力を検査する前に、約5〜10分待ちます。 いくつかのノードでステータスとしてNotReady
がまだ残っている場合は、前の手順でコマンドを確認して再実行する必要がある場合があります。
クラスタが正常に検証されたので、クラスタでサンプルのNginxアプリケーションをスケジュールしましょう。
ステップ7—クラスターでのアプリケーションの実行
これで、コンテナー化されたアプリケーションをクラスターにデプロイできます。 慣れるために、DeploymentsとServicesを使用してNginxをデプロイし、このアプリケーションをクラスターにデプロイする方法を確認しましょう。 Dockerイメージ名と関連するフラグ(ports
やvolumes
など)を変更すれば、他のコンテナー化されたアプリケーションにも以下のコマンドを使用できます。
マスターノード内で、次のコマンドを実行して、nginx
という名前のデプロイメントを作成します。
kubectl create deployment nginx --image=nginx
デプロイはKubernetesオブジェクトの一種であり、クラスターの存続期間中にポッドがクラッシュした場合でも、定義されたテンプレートに基づいて指定された数のポッドが常に実行されるようにします。 上記のデプロイでは、Dockerレジストリの Nginx DockerImageから1つのコンテナーでポッドが作成されます。
次に、次のコマンドを実行して、アプリを公開するnginx
という名前のサービスを作成します。 これは、 NodePort を介して行われます。これは、クラスターの各ノードで開かれた任意のポートを介してポッドにアクセスできるようにするスキームです。
kubectl expose deploy nginx --port 80 --target-port 80 --type NodePort
サービスは、クラスター内部サービスを内部と外部の両方のクライアントに公開する別のタイプのKubernetesオブジェクトです。 また、複数のポッドへのリクエストの負荷分散も可能であり、Kubernetesの不可欠なコンポーネントであり、他のコンポーネントと頻繁にやり取りします。
次のコマンドを実行します。
kubectl get services
これにより、次のようなテキストが出力されます。
OutputNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 1d nginx NodePort 10.109.228.209 <none> 80:nginx_port/TCP 40m
上記の出力の3行目から、Nginxが実行されているポートを取得できます。 Kubernetesは、30000
より大きいランダムなポートを自動的に割り当てますが、ポートが別のサービスによってバインドされていないことを確認します。
すべてが機能していることをテストするには、ローカルマシンのブラウザからhttp://worker_1_ip:nginx_port
またはhttp://worker_2_ip:nginx_port
にアクセスします。 Nginxのおなじみのウェルカムページが表示されます。
Nginxアプリケーションを削除する場合は、最初にマスターノードからnginx
サービスを削除します。
kubectl delete service nginx
以下を実行して、サービスが削除されたことを確認します。
kubectl get services
次の出力が表示されます。
OutputNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 1d
次に、デプロイメントを削除します。
kubectl delete deployment nginx
以下を実行して、これが機能したことを確認します。
kubectl get deployments
OutputNo resources found.
結論
このガイドでは、自動化にKubeadmとAnsibleを使用して、CentOS7でKubernetesクラスターを正常にセットアップしました。
セットアップが完了したクラスターをどうするか迷っている場合は、次のステップとして、独自のアプリケーションとサービスをクラスターに快適にデプロイできるようにすることをお勧めします。 プロセスをガイドするための詳細情報を含むリンクのリストは次のとおりです。
- アプリケーションのDocker化-Dockerを使用してアプリケーションをコンテナ化する方法の詳細を示す例を示します。
- ポッドの概要-ポッドがどのように機能するか、および他のKubernetesオブジェクトとの関係について詳しく説明します。 ポッドはKubernetesに遍在しているため、ポッドを理解すると作業が容易になります。
- 展開の概要-これは展開の概要を提供します。 デプロイメントなどのコントローラーは、スケーリングや異常なアプリケーションの自動修復のためにステートレスアプリケーションで頻繁に使用されるため、どのように機能するかを理解しておくと便利です。
- サービスの概要-これは、Kubernetesクラスターで頻繁に使用されるもう1つのオブジェクトであるサービスを対象としています。 サービスの種類とそのオプションを理解することは、ステートレスアプリケーションとステートフルアプリケーションの両方を実行するために不可欠です。
調べることができるその他の重要な概念は、ボリューム、イングレス、およびシークレットです。これらはすべて、実稼働アプリケーションをデプロイするときに役立ちます。
Kubernetesには多くの機能と機能があります。 Kubernetes公式ドキュメントは、概念について学び、タスク固有のガイドを見つけ、さまざまなオブジェクトのAPIリファレンスを検索するのに最適な場所です。