├── .gitignore
├── CONTRIBUTING.md
├── COPYRIGHT.md
├── LICENSE
├── README.md
├── deployments
├── coredns.yaml
└── kube-dns.yaml
└── docs
├── 01-prerequisites.md
├── 02-client-tools.md
├── 03-compute-resources.md
├── 04-certificate-authority.md
├── 05-kubernetes-configuration-files.md
├── 06-data-encryption-keys.md
├── 07-bootstrapping-etcd.md
├── 08-bootstrapping-kubernetes-controllers.md
├── 09-bootstrapping-kubernetes-workers.md
├── 10-configuring-kubectl.md
├── 11-pod-network-routes.md
├── 12-dns-addon.md
├── 13-smoke-test.md
├── 14-cleanup.md
└── images
└── tmux-screenshot.png
/.gitignore:
--------------------------------------------------------------------------------
1 | admin-csr.json
2 | admin-key.pem
3 | admin.csr
4 | admin.pem
5 | admin.kubeconfig
6 | ca-config.json
7 | ca-csr.json
8 | ca-key.pem
9 | ca.csr
10 | ca.pem
11 | encryption-config.yaml
12 | kube-controller-manager-csr.json
13 | kube-controller-manager-key.pem
14 | kube-controller-manager.csr
15 | kube-controller-manager.kubeconfig
16 | kube-controller-manager.pem
17 | kube-scheduler-csr.json
18 | kube-scheduler-key.pem
19 | kube-scheduler.csr
20 | kube-scheduler.kubeconfig
21 | kube-scheduler.pem
22 | kube-proxy-csr.json
23 | kube-proxy-key.pem
24 | kube-proxy.csr
25 | kube-proxy.kubeconfig
26 | kube-proxy.pem
27 | kubernetes-csr.json
28 | kubernetes-key.pem
29 | kubernetes.csr
30 | kubernetes.pem
31 | worker-0-csr.json
32 | worker-0-key.pem
33 | worker-0.csr
34 | worker-0.kubeconfig
35 | worker-0.pem
36 | worker-1-csr.json
37 | worker-1-key.pem
38 | worker-1.csr
39 | worker-1.kubeconfig
40 | worker-1.pem
41 | worker-2-csr.json
42 | worker-2-key.pem
43 | worker-2.csr
44 | worker-2.kubeconfig
45 | worker-2.pem
46 | service-account-key.pem
47 | service-account.csr
48 | service-account.pem
49 | service-account-csr.json
50 | *.swp
51 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | This project is made possible by contributors like YOU! While all contributions are welcomed, please be sure and follow the following suggestions to help your PR get merged.
2 |
3 | ## License
4 |
5 | This project uses an [Apache license](LICENSE). Be sure you're comfortable with the implications of that before working up a patch.
6 |
7 | ## Review and merge process
8 |
9 | Review and merge duties are managed by [@kelseyhightower](https://github.com/kelseyhightower). Expect some burden of proof for demonstrating the marginal value of adding new content to the tutorial.
10 |
11 | Here are some examples of the review and justification process:
12 | - [#208](https://github.com/kelseyhightower/kubernetes-the-hard-way/pull/208)
13 | - [#282](https://github.com/kelseyhightower/kubernetes-the-hard-way/pull/282)
14 |
15 | ## Notes on minutiae
16 |
17 | If you find a bug that breaks the guide, please do submit it. If you are considering a minor copy edit for tone, grammar, or simple inconsistent whitespace, consider the tradeoff between maintainer time and community benefit before investing too much of your time.
18 |
19 |
--------------------------------------------------------------------------------
/COPYRIGHT.md:
--------------------------------------------------------------------------------
1 | # Copyright
2 |
3 | 
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Kubernetes The Hard Way(日本語版)
2 |
3 | ### 【注意】この翻訳は、1.21.0時点で動作が確認できているバージョンの凍結版です。動作確認できた次のバージョンがリリースされない限り、しばらくの間更新の予定はありません。Typoや誤訳などを見つけた場合はPR、Issue、または[Twitter](https://twitter.com/_inductor_)にてお知らせください。
4 |
5 | 本チュートリアルでは、Kubernetesを地道にセットアップする方法を説明します。本ガイドは、Kubernetesクラスターを立てるための自動化コマンドを探している人には向いていません。そういう人は、[Google Kubernetes Engine](https://cloud.google.com/kubernetes-engine)や[Getting Started Guides](https://kubernetes.io/docs/setup)を御覧ください。
6 |
7 | Kubernetes The Hard Wayは勉強に適しています。長い道のりを経て、Kubernetesクラスターを起動するのに必要な各タスクを理解してください。
8 |
9 | > 本チュートリアルの結果はプロダクションレディではなく、コミュニティからのサポートも限られていますが、だからといって勉強しない理由にはなりません!
10 |
11 | ## Copyright
12 |
13 | 
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
14 |
15 |
16 | ## 対象者
17 |
18 | 本チュートリアルの対象読者は、Kubernetesの本番クラスターのサポートを予定していて、すべてがどのように連携しているかを理解したいという人です。
19 |
20 | ## クラスターの詳細
21 |
22 | Kubernetes The Hard Wayは、コンポーネント間のエンドツーエンドの暗号化とRBAC認証を使用して、可用性の高いKubernetesクラスターをブートストラップする手順を説明します。
23 |
24 | * [kubernetes](https://github.com/kubernetes/kubernetes) v1.21.0
25 | * [containerd](https://github.com/containerd/containerd) v1.4.4
26 | * [coredns](https://github.com/coredns/coredns) v1.8.3
27 | * [cni](https://github.com/containernetworking/cni) v0.9.1
28 | * [etcd](https://github.com/etcd-io/etcd) v3.4.15
29 |
30 | ## 実習内容
31 |
32 | 本チュートリアルは、Google Cloud Platformへのアクセス権があることを前提としています。GCPは基本的なインフラストラクチャ要件に使用されますが、本チュートリアルで学習したレッスンは他のプラットフォームにも適用できます。
33 |
34 | * [前提条件](docs/01-prerequisites.md)
35 | * [クライアントツールのインストール](docs/02-client-tools.md)
36 | * [計算資源のプロビジョニング](docs/03-compute-resources.md)
37 | * [CA証明書のプロビジョニングとTLS証明書の生成](docs/04-certificate-authority.md)
38 | * [認証用Kubernetes設定ファイルの生成](docs/05-kubernetes-configuration-files.md)
39 | * [データ暗号化の設定とキーの生成](docs/06-data-encryption-keys.md)
40 | * [etcdクラスターのブートストラップ](docs/07-bootstrapping-etcd.md)
41 | * [Kubernetesコントロールプレーンのブートストラップ](docs/08-bootstrapping-kubernetes-controllers.md)
42 | * [Kubenretesワーカーノードのブートストラップ](docs/09-bootstrapping-kubernetes-workers.md)
43 | * [リモートアクセス用のkubectl設定](docs/10-configuring-kubectl.md)
44 | * [Podネットワークルートのプロビジョニング](docs/11-pod-network-routes.md)
45 | * [DNSクラスターアドオンのデプロイ](docs/12-dns-addon.md)
46 | * [スモークテスト](docs/13-smoke-test.md)
47 | * [お掃除](docs/14-cleanup.md)
48 |
--------------------------------------------------------------------------------
/deployments/coredns.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: ServiceAccount
3 | metadata:
4 | name: coredns
5 | namespace: kube-system
6 | ---
7 | apiVersion: rbac.authorization.k8s.io/v1
8 | kind: ClusterRole
9 | metadata:
10 | labels:
11 | kubernetes.io/bootstrapping: rbac-defaults
12 | name: system:coredns
13 | rules:
14 | - apiGroups:
15 | - ""
16 | resources:
17 | - endpoints
18 | - services
19 | - pods
20 | - namespaces
21 | verbs:
22 | - list
23 | - watch
24 | - apiGroups:
25 | - ""
26 | resources:
27 | - nodes
28 | verbs:
29 | - get
30 | ---
31 | apiVersion: rbac.authorization.k8s.io/v1
32 | kind: ClusterRoleBinding
33 | metadata:
34 | annotations:
35 | rbac.authorization.kubernetes.io/autoupdate: "true"
36 | labels:
37 | kubernetes.io/bootstrapping: rbac-defaults
38 | name: system:coredns
39 | roleRef:
40 | apiGroup: rbac.authorization.k8s.io
41 | kind: ClusterRole
42 | name: system:coredns
43 | subjects:
44 | - kind: ServiceAccount
45 | name: coredns
46 | namespace: kube-system
47 | ---
48 | apiVersion: v1
49 | kind: ConfigMap
50 | metadata:
51 | name: coredns
52 | namespace: kube-system
53 | data:
54 | Corefile: |
55 | .:53 {
56 | errors
57 | health
58 | ready
59 | kubernetes cluster.local in-addr.arpa ip6.arpa {
60 | pods insecure
61 | fallthrough in-addr.arpa ip6.arpa
62 | }
63 | prometheus :9153
64 | cache 30
65 | loop
66 | reload
67 | loadbalance
68 | }
69 | ---
70 | apiVersion: apps/v1
71 | kind: Deployment
72 | metadata:
73 | name: coredns
74 | namespace: kube-system
75 | labels:
76 | k8s-app: kube-dns
77 | kubernetes.io/name: "CoreDNS"
78 | spec:
79 | replicas: 2
80 | strategy:
81 | type: RollingUpdate
82 | rollingUpdate:
83 | maxUnavailable: 1
84 | selector:
85 | matchLabels:
86 | k8s-app: kube-dns
87 | template:
88 | metadata:
89 | labels:
90 | k8s-app: kube-dns
91 | spec:
92 | priorityClassName: system-cluster-critical
93 | serviceAccountName: coredns
94 | tolerations:
95 | - key: "CriticalAddonsOnly"
96 | operator: "Exists"
97 | nodeSelector:
98 | beta.kubernetes.io/os: linux
99 | containers:
100 | - name: coredns
101 | image: coredns/coredns:1.7.0
102 | imagePullPolicy: IfNotPresent
103 | resources:
104 | limits:
105 | memory: 170Mi
106 | requests:
107 | cpu: 100m
108 | memory: 70Mi
109 | args: [ "-conf", "/etc/coredns/Corefile" ]
110 | volumeMounts:
111 | - name: config-volume
112 | mountPath: /etc/coredns
113 | readOnly: true
114 | ports:
115 | - containerPort: 53
116 | name: dns
117 | protocol: UDP
118 | - containerPort: 53
119 | name: dns-tcp
120 | protocol: TCP
121 | - containerPort: 9153
122 | name: metrics
123 | protocol: TCP
124 | securityContext:
125 | allowPrivilegeEscalation: false
126 | capabilities:
127 | add:
128 | - NET_BIND_SERVICE
129 | drop:
130 | - all
131 | readOnlyRootFilesystem: true
132 | livenessProbe:
133 | httpGet:
134 | path: /health
135 | port: 8080
136 | scheme: HTTP
137 | initialDelaySeconds: 60
138 | timeoutSeconds: 5
139 | successThreshold: 1
140 | failureThreshold: 5
141 | readinessProbe:
142 | httpGet:
143 | path: /ready
144 | port: 8181
145 | scheme: HTTP
146 | dnsPolicy: Default
147 | volumes:
148 | - name: config-volume
149 | configMap:
150 | name: coredns
151 | items:
152 | - key: Corefile
153 | path: Corefile
154 | ---
155 | apiVersion: v1
156 | kind: Service
157 | metadata:
158 | name: kube-dns
159 | namespace: kube-system
160 | annotations:
161 | prometheus.io/port: "9153"
162 | prometheus.io/scrape: "true"
163 | labels:
164 | k8s-app: kube-dns
165 | kubernetes.io/cluster-service: "true"
166 | kubernetes.io/name: "CoreDNS"
167 | spec:
168 | selector:
169 | k8s-app: kube-dns
170 | clusterIP: 10.32.0.10
171 | ports:
172 | - name: dns
173 | port: 53
174 | protocol: UDP
175 | - name: dns-tcp
176 | port: 53
177 | protocol: TCP
178 | - name: metrics
179 | port: 9153
180 | protocol: TCP
181 |
--------------------------------------------------------------------------------
/deployments/kube-dns.yaml:
--------------------------------------------------------------------------------
1 | # Copyright 2016 The Kubernetes Authors.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | apiVersion: v1
16 | kind: Service
17 | metadata:
18 | name: kube-dns
19 | namespace: kube-system
20 | labels:
21 | k8s-app: kube-dns
22 | kubernetes.io/cluster-service: "true"
23 | addonmanager.kubernetes.io/mode: Reconcile
24 | kubernetes.io/name: "KubeDNS"
25 | spec:
26 | selector:
27 | k8s-app: kube-dns
28 | clusterIP: 10.32.0.10
29 | ports:
30 | - name: dns
31 | port: 53
32 | protocol: UDP
33 | - name: dns-tcp
34 | port: 53
35 | protocol: TCP
36 | ---
37 | apiVersion: v1
38 | kind: ServiceAccount
39 | metadata:
40 | name: kube-dns
41 | namespace: kube-system
42 | labels:
43 | kubernetes.io/cluster-service: "true"
44 | addonmanager.kubernetes.io/mode: Reconcile
45 | ---
46 | apiVersion: v1
47 | kind: ConfigMap
48 | metadata:
49 | name: kube-dns
50 | namespace: kube-system
51 | labels:
52 | addonmanager.kubernetes.io/mode: EnsureExists
53 | ---
54 | apiVersion: apps/v1
55 | kind: Deployment
56 | metadata:
57 | name: kube-dns
58 | namespace: kube-system
59 | labels:
60 | k8s-app: kube-dns
61 | kubernetes.io/cluster-service: "true"
62 | addonmanager.kubernetes.io/mode: Reconcile
63 | spec:
64 | # replicas: not specified here:
65 | # 1. In order to make Addon Manager do not reconcile this replicas parameter.
66 | # 2. Default is 1.
67 | # 3. Will be tuned in real time if DNS horizontal auto-scaling is turned on.
68 | strategy:
69 | rollingUpdate:
70 | maxSurge: 10%
71 | maxUnavailable: 0
72 | selector:
73 | matchLabels:
74 | k8s-app: kube-dns
75 | template:
76 | metadata:
77 | labels:
78 | k8s-app: kube-dns
79 | annotations:
80 | scheduler.alpha.kubernetes.io/critical-pod: ''
81 | spec:
82 | tolerations:
83 | - key: "CriticalAddonsOnly"
84 | operator: "Exists"
85 | volumes:
86 | - name: kube-dns-config
87 | configMap:
88 | name: kube-dns
89 | optional: true
90 | containers:
91 | - name: kubedns
92 | image: gcr.io/google_containers/k8s-dns-kube-dns-amd64:1.14.7
93 | resources:
94 | # TODO: Set memory limits when we've profiled the container for large
95 | # clusters, then set request = limit to keep this container in
96 | # guaranteed class. Currently, this container falls into the
97 | # "burstable" category so the kubelet doesn't backoff from restarting it.
98 | limits:
99 | memory: 170Mi
100 | requests:
101 | cpu: 100m
102 | memory: 70Mi
103 | livenessProbe:
104 | httpGet:
105 | path: /healthcheck/kubedns
106 | port: 10054
107 | scheme: HTTP
108 | initialDelaySeconds: 60
109 | timeoutSeconds: 5
110 | successThreshold: 1
111 | failureThreshold: 5
112 | readinessProbe:
113 | httpGet:
114 | path: /readiness
115 | port: 8081
116 | scheme: HTTP
117 | # we poll on pod startup for the Kubernetes master service and
118 | # only setup the /readiness HTTP server once that's available.
119 | initialDelaySeconds: 3
120 | timeoutSeconds: 5
121 | args:
122 | - --domain=cluster.local.
123 | - --dns-port=10053
124 | - --config-dir=/kube-dns-config
125 | - --v=2
126 | env:
127 | - name: PROMETHEUS_PORT
128 | value: "10055"
129 | ports:
130 | - containerPort: 10053
131 | name: dns-local
132 | protocol: UDP
133 | - containerPort: 10053
134 | name: dns-tcp-local
135 | protocol: TCP
136 | - containerPort: 10055
137 | name: metrics
138 | protocol: TCP
139 | volumeMounts:
140 | - name: kube-dns-config
141 | mountPath: /kube-dns-config
142 | - name: dnsmasq
143 | image: gcr.io/google_containers/k8s-dns-dnsmasq-nanny-amd64:1.14.7
144 | livenessProbe:
145 | httpGet:
146 | path: /healthcheck/dnsmasq
147 | port: 10054
148 | scheme: HTTP
149 | initialDelaySeconds: 60
150 | timeoutSeconds: 5
151 | successThreshold: 1
152 | failureThreshold: 5
153 | args:
154 | - -v=2
155 | - -logtostderr
156 | - -configDir=/etc/k8s/dns/dnsmasq-nanny
157 | - -restartDnsmasq=true
158 | - --
159 | - -k
160 | - --cache-size=1000
161 | - --no-negcache
162 | - --log-facility=-
163 | - --server=/cluster.local/127.0.0.1#10053
164 | - --server=/in-addr.arpa/127.0.0.1#10053
165 | - --server=/ip6.arpa/127.0.0.1#10053
166 | ports:
167 | - containerPort: 53
168 | name: dns
169 | protocol: UDP
170 | - containerPort: 53
171 | name: dns-tcp
172 | protocol: TCP
173 | # see: https://github.com/kubernetes/kubernetes/issues/29055 for details
174 | resources:
175 | requests:
176 | cpu: 150m
177 | memory: 20Mi
178 | volumeMounts:
179 | - name: kube-dns-config
180 | mountPath: /etc/k8s/dns/dnsmasq-nanny
181 | - name: sidecar
182 | image: gcr.io/google_containers/k8s-dns-sidecar-amd64:1.14.7
183 | livenessProbe:
184 | httpGet:
185 | path: /metrics
186 | port: 10054
187 | scheme: HTTP
188 | initialDelaySeconds: 60
189 | timeoutSeconds: 5
190 | successThreshold: 1
191 | failureThreshold: 5
192 | args:
193 | - --v=2
194 | - --logtostderr
195 | - --probe=kubedns,127.0.0.1:10053,kubernetes.default.svc.cluster.local,5,SRV
196 | - --probe=dnsmasq,127.0.0.1:53,kubernetes.default.svc.cluster.local,5,SRV
197 | ports:
198 | - containerPort: 10054
199 | name: metrics
200 | protocol: TCP
201 | resources:
202 | requests:
203 | memory: 20Mi
204 | cpu: 10m
205 | dnsPolicy: Default # Don't use cluster DNS.
206 | serviceAccountName: kube-dns
207 |
--------------------------------------------------------------------------------
/docs/01-prerequisites.md:
--------------------------------------------------------------------------------
1 | # 前提条件
2 |
3 | ## Google Cloud Platform
4 |
5 | 本チュートリアルでは、Kubernetesクラスターのブートストラップに必要な計算資源のプロビジョニングを一から効率的に行うために[Google Cloud Platform](https://cloud.google.com/)を活用しています。300ドル分の無料クレジットに[サインアップ](https://cloud.google.com/free/)してください。
6 |
7 | 本チュートリアルの[推定実行コスト](https://cloud.google.com/products/calculator#id=873932bc-0840-4176-b0fa-a8cfd4ca61ae)は1時間あたり$0.23(1日あたり$5.50)です。
8 |
9 | > 本チュートリアルに必要な計算資源は、Google Cloud Platformの無料枠を超えています。
10 |
11 | ## Google Cloud Platform SDK
12 |
13 | ### Google Cloud SDKのインストール
14 |
15 | Google Cloud SDKの[ドキュメント](https://cloud.google.com/sdk/)に従って `gcloud` コマンドをインストールし、設定してください。
16 |
17 | Google Cloud SDKのバージョンが338.0.0以上であることを確認してください:
18 |
19 | ```
20 | gcloud version
21 | ```
22 |
23 | ### デフォルトのリージョンとゾーンの設定
24 |
25 | 本チュートリアルでは、デフォルトのリージョンとゾーンが既に設定されている前提で進められます。
26 |
27 | はじめて `gcloud` コマンドをお使いの場合、`init` を使うと最も簡単に初期設定が行えます:
28 |
29 | ```
30 | gcloud init
31 | ```
32 |
33 | その後、ご自身のGoogleユーザーの認証情報でgcloudがCloud Platformにアクセスすることを必ず確認してください:
34 |
35 | ```
36 | gcloud auth login
37 | ```
38 |
39 | 次に、デフォルトのリージョンを設定します:
40 |
41 | ```
42 | gcloud config set compute/region us-west1
43 | ```
44 |
45 | 次に、デフォルトのゾーンを設定します:
46 |
47 | ```
48 | gcloud config set compute/zone us-west1-c
49 | ```
50 |
51 | > 追加で利用できるリージョンやゾーンを確認するには、`gcloud compute zones list` を使ってください。
52 |
53 | ## tmuxを使った並列なコマンド実行
54 |
55 | [tmux](https://github.com/tmux/tmux/wiki)を使用すると、複数のcomputeインスタンスで同時にコマンドを実行できます。本チュートリアルでは、同じコマンドを複数のコンピュートインスタンスで実行する必要がある場合があります。その場合、tmuxを使用して、プロビジョニングプロセスを高速化するために同期を有効にした複数のペインにウィンドウを分割することを検討してください。
56 |
57 | > tmuxの使用はオプションであり、このチュートリアルを完了するために必須ではありません。
58 |
59 | 
60 |
61 | > Enable synchronize-panes by pressing `ctrl+b` followed by `shift+:`. Next type `set synchronize-panes on` at the prompt. To disable synchronization: `set synchronize-panes off`.
62 |
63 | Next: [クライアントツールのインストール](02-client-tools.md)
64 |
--------------------------------------------------------------------------------
/docs/02-client-tools.md:
--------------------------------------------------------------------------------
1 | # クライアントツールのインストール
2 |
3 | 本実習では、チュートリアルの実行に必要なコマンドである[cfssl](https://github.com/cloudflare/cfssl)、[cfssljson](https://github.com/cloudflare/cfssl)、[kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl)をインストールします。
4 |
5 |
6 | ## cfsslのインストール
7 |
8 | [公開鍵基盤](https://ja.wikipedia.org/wiki/%E5%85%AC%E9%96%8B%E9%8D%B5%E5%9F%BA%E7%9B%A4)のプロビジョニングとTLS証明書の生成には、`cfssl`および`cfssljson`コマンドラインユーティリティが使用されます。
9 |
10 | `cfssl`と`cfssljson`をダウンロードし、インストールします:
11 |
12 | ### macOS
13 |
14 | ```
15 | curl -o cfssl https://storage.googleapis.com/kubernetes-the-hard-way/cfssl/1.4.1/darwin/cfssl
16 | curl -o cfssljson https://storage.googleapis.com/kubernetes-the-hard-way/cfssl/1.4.1/darwin/cfssljson
17 | ```
18 |
19 | ```
20 | chmod +x cfssl cfssljson
21 | ```
22 |
23 | ```
24 | sudo mv cfssl cfssljson /usr/local/bin/
25 | ```
26 |
27 | macOSユーザーの中でビルド済みバイナリーに問題があった人は、[Homebrew](https://brew.sh)を使うと改善されるかもしれません:
28 |
29 | ```
30 | brew install cfssl
31 | ```
32 |
33 | ### Linux
34 |
35 | ```
36 | wget -q --show-progress --https-only --timestamping \
37 | https://storage.googleapis.com/kubernetes-the-hard-way/cfssl/1.4.1/linux/cfssl \
38 | https://storage.googleapis.com/kubernetes-the-hard-way/cfssl/1.4.1/linux/cfssljson
39 | ```
40 |
41 | ```
42 | chmod +x cfssl cfssljson
43 | ```
44 |
45 | ```
46 | sudo mv cfssl cfssljson /usr/local/bin/
47 | ```
48 |
49 | ### 検証
50 |
51 | インストールされた`cfssl`と`cfssljson`のバージョンが1.4.1以上であることを検証します:
52 |
53 | ```
54 | cfssl version
55 | ```
56 |
57 | > 出力結果
58 |
59 | ```
60 | Version: 1.4.1
61 | Runtime: go1.12.12
62 | ```
63 |
64 | ```
65 | cfssljson --version
66 | ```
67 | ```
68 | Version: 1.4.1
69 | Runtime: go1.12.12
70 | ```
71 |
72 | ## kubectlのインストール
73 |
74 | `kubectl`コマンドは、KubernetesのAPIサーバーとの対話に使用されます。公式リリースバイナリーから`kubectl`をダウンロードしてインストールします:
75 |
76 | ### macOS
77 |
78 | ```
79 | curl -o kubectl https://storage.googleapis.com/kubernetes-release/release/v1.21.0/bin/darwin/amd64/kubectl
80 | ```
81 |
82 | ```
83 | chmod +x kubectl
84 | ```
85 |
86 | ```
87 | sudo mv kubectl /usr/local/bin/
88 | ```
89 |
90 | ### Linux
91 |
92 | ```
93 | wget https://storage.googleapis.com/kubernetes-release/release/v1.21.0/bin/linux/amd64/kubectl
94 | ```
95 |
96 | ```
97 | chmod +x kubectl
98 | ```
99 |
100 | ```
101 | sudo mv kubectl /usr/local/bin/
102 | ```
103 |
104 | ### 検証
105 |
106 | インストールされた`kubectl`のバージョンが1.21.0以上であることを検証します:
107 |
108 | ```
109 | kubectl version --client
110 | ```
111 |
112 | > 出力結果
113 |
114 | ```
115 | Client Version: version.Info{Major:"1", Minor:"21", GitVersion:"v1.21.0", GitCommit:"cb303e613a121a29364f75cc67d3d580833a7479", GitTreeState:"clean", BuildDate:"2021-04-08T16:31:21Z", GoVersion:"go1.16.1", Compiler:"gc", Platform:"linux/amd64"}
116 | ```
117 |
118 | Next: [計算資源のプロビジョニング](03-compute-resources.md)
119 |
--------------------------------------------------------------------------------
/docs/03-compute-resources.md:
--------------------------------------------------------------------------------
1 | # 計算資源のプロビジョニング
2 |
3 | Kubernetesには、コントロールプレーンとコンテナが最終的に実行されるワーカーノードをホストするマシンのセットが必要です。本実習では、安全で可用性の高いKubernetesクラスターを単一の[ゾーン](https://cloud.google.com/compute/docs/regions-zones/regions-zones)で実行するために必要な計算資源をプロビジョニングします。
4 |
5 | > デフォルトのゾーンおよびリージョンが、[前提条件](01-prerequisites.md#デフォルトのリージョンとゾーンの設定)ページの説明通りに設定されていることを確認してください。
6 |
7 | ## ネットワーク
8 |
9 | Kubernetesの[ネットワークモデル](https://kubernetes.io/docs/concepts/cluster-administration/networking/#kubernetes-model)は、コンテナとノードが相互に通信できるフラットなネットワークを想定しています。これが望ましくない場合は、[ネットワークポリシー](https://kubernetes.io/docs/concepts/services-networking/network-policies/)を使ってコンテナのグループが相互に、もしくは外部ネットワークエンドポイントと通信することを制限できます。
10 |
11 | > ネットワークポリシーの設定は、本チュートリアルの対象外です。
12 |
13 | ### 仮想プライベートクラウドネットワーク(VPC)
14 |
15 | 本セクションではKubernetesクラスタをホストする専用の[仮想プライベートクラウド](https://cloud.google.com/compute/docs/networks-and-firewalls#networks)(VPC)を設定します。
16 |
17 | `kubernetes-the-hard-way`という名前のカスタムVPCネットワークを作成します:
18 |
19 | ```
20 | gcloud compute networks create kubernetes-the-hard-way --subnet-mode custom
21 | ```
22 |
23 | [サブネット](https://cloud.google.com/compute/docs/vpc/#vpc_networks_and_subnets)は、Kubernetesクラスター内の各ノードにプライベートIPアドレスを割り当てるのに十分なIPアドレス範囲でプロビジョニングする必要があります。
24 |
25 | `kubernetes`という名前のサブネットを`kubernetes-the-hard-way`VPCネットワーク内に作成します:
26 |
27 | ```
28 | gcloud compute networks subnets create kubernetes \
29 | --network kubernetes-the-hard-way \
30 | --range 10.240.0.0/24
31 | ```
32 |
33 | > IPアドレス範囲`10.240.0.0/24`を指定すると、254個までのインスタンスまで作成することができます。
34 |
35 | ### Firewall Rules
36 |
37 | 内部通信にて全プロトコルを許可するファイアウォールルールを作成します:
38 |
39 | ```
40 | gcloud compute firewall-rules create kubernetes-the-hard-way-allow-internal \
41 | --allow tcp,udp,icmp \
42 | --network kubernetes-the-hard-way \
43 | --source-ranges 10.240.0.0/24,10.200.0.0/16
44 | ```
45 |
46 | 外部からのSSH、ICMP、およびHTTPS通信を許可するファイアウォールルールを作成します:
47 |
48 | ```
49 | gcloud compute firewall-rules create kubernetes-the-hard-way-allow-external \
50 | --allow tcp:22,tcp:6443,icmp \
51 | --network kubernetes-the-hard-way \
52 | --source-ranges 0.0.0.0/0
53 | ```
54 |
55 | > KubernetesのAPIサーバーをリモートクライアントに公開するために[外部ロードバランサ](https://cloud.google.com/compute/docs/load-balancing/network/)が利用されます。
56 |
57 | `Kubernetes-the-hard-way`VPCネットワークにおけるファイアウォールルール一覧を確認します:
58 |
59 | ```
60 | gcloud compute firewall-rules list --filter="network:kubernetes-the-hard-way"
61 | ```
62 |
63 | > 出力結果
64 |
65 | ```
66 | NAME NETWORK DIRECTION PRIORITY ALLOW DENY DISABLED
67 | kubernetes-the-hard-way-allow-external kubernetes-the-hard-way INGRESS 1000 tcp:22,tcp:6443,icmp False
68 | kubernetes-the-hard-way-allow-internal kubernetes-the-hard-way INGRESS 1000 tcp,udp,icmp False
69 | ```
70 |
71 | ### Kubernetesの公開IPアドレス
72 |
73 | KubernetesのAPIサーバの前面に置かれる外部ロードバランサにアタッチする静的IPアドレスを割り当てます:
74 |
75 | ```
76 | gcloud compute addresses create kubernetes-the-hard-way \
77 | --region $(gcloud config get-value compute/region)
78 | ```
79 |
80 | `kubernetes-the-hard-way`という名前の静的IPアドレスがデフォルトリージョンに作成されたことを確認します:
81 |
82 | ```
83 | gcloud compute addresses list --filter="name=('kubernetes-the-hard-way')"
84 | ```
85 |
86 | > 出力結果
87 |
88 | ```
89 | NAME ADDRESS/RANGE TYPE PURPOSE NETWORK REGION SUBNET STATUS
90 | kubernetes-the-hard-way XX.XXX.XXX.XXX EXTERNAL us-west1 RESERVED
91 | ```
92 |
93 | ## インスタンス
94 |
95 | 本実習のインスタンスでは、コンテナランタイムの[containerd](https://github.com/containerd/containerd)にて推奨される[Ubuntu Server](https://www.ubuntu.com/server) 20.04を使用します。各インスタンスは、Kubernetesのブートストラッピング処理を単純化するために、固定のプライベートIPアドレスでプロビジョニングされます。
96 |
97 | ### Kubernetesコントロールプレーン
98 |
99 | Kubernetesコントロールプレーンをホストする3つのインスタンスを作成します:
100 |
101 | ```sh
102 | for i in 0 1 2; do
103 | gcloud compute instances create controller-${i} \
104 | --async \
105 | --boot-disk-size 200GB \
106 | --can-ip-forward \
107 | --image-family ubuntu-2004-lts \
108 | --image-project ubuntu-os-cloud \
109 | --machine-type e2-standard-2 \
110 | --private-network-ip 10.240.0.1${i} \
111 | --scopes compute-rw,storage-ro,service-management,service-control,logging-write,monitoring \
112 | --subnet kubernetes \
113 | --tags kubernetes-the-hard-way,controller
114 | done
115 | ```
116 |
117 | ### Kubernetesワーカー
118 |
119 | 各ワーカーインスタンスは、KubernetesクラスターにおけるCIDR範囲からのPodサブネット割り当てを必要とします。Podサブネットの割り当ては、後の実習にてコンテナネットワークの設定に使用します。`pod-cidr`インスタンスメタデータは、実行時にインスタンスを計算するためのPodサブネット割り当てを公開するために使用されます。
120 |
121 | > KubernetesクラスターのCIDR範囲は、コントローラーマネージャーの`--cluster-cidr`フラグで定義されます。本チュートリアルでは、クラスターのCIDR範囲を`10.200.0.0/16に設定します。これは、254のサブネットをサポートします。
122 |
123 | Kubernetesワーカーノードをホストするインスタンスを3つ作成します:
124 |
125 | ```sh
126 | for i in 0 1 2; do
127 | gcloud compute instances create worker-${i} \
128 | --async \
129 | --boot-disk-size 200GB \
130 | --can-ip-forward \
131 | --image-family ubuntu-2004-lts \
132 | --image-project ubuntu-os-cloud \
133 | --machine-type e2-standard-2 \
134 | --metadata pod-cidr=10.200.${i}.0/24 \
135 | --private-network-ip 10.240.0.2${i} \
136 | --scopes compute-rw,storage-ro,service-management,service-control,logging-write,monitoring \
137 | --subnet kubernetes \
138 | --tags kubernetes-the-hard-way,worker
139 | done
140 | ```
141 |
142 | ### 検証
143 |
144 | デフォルトのゾーン内にあるインスタンスの一覧を表示します:
145 |
146 | ```
147 | gcloud compute instances list --filter="tags.items=kubernetes-the-hard-way"
148 | ```
149 |
150 | > 出力結果
151 |
152 | ```
153 | NAME ZONE MACHINE_TYPE PREEMPTIBLE INTERNAL_IP EXTERNAL_IP STATUS
154 | controller-0 us-west1-c e2-standard-2 10.240.0.10 XX.XX.XX.XXX RUNNING
155 | controller-1 us-west1-c e2-standard-2 10.240.0.11 XX.XXX.XXX.XX RUNNING
156 | controller-2 us-west1-c e2-standard-2 10.240.0.12 XX.XXX.XX.XXX RUNNING
157 | worker-0 us-west1-c e2-standard-2 10.240.0.20 XX.XX.XXX.XXX RUNNING
158 | worker-1 us-west1-c e2-standard-2 10.240.0.21 XX.XX.XX.XXX RUNNING
159 | worker-2 us-west1-c e2-standard-2 10.240.0.22 XX.XXX.XX.XX RUNNING
160 | ```
161 |
162 | ## SSHアクセスの設定
163 |
164 | SSHは、コントローラーおよびワーカーインスタンスの設定に使用されます。初めてインスタンスに接続するとSSHキーが生成され、プロジェクトまたはインスタンスのメタデータに格納されます ([インスタンスへの接続](https://cloud.google.com/compute/docs/instances/connecting-to-instance)のマニュアルを参照してください)。
165 |
166 | 試しに、`controller-0`インスタンスにSSHしてみます:
167 |
168 | ```
169 | gcloud compute ssh controller-0
170 | ```
171 |
172 | インスタンスに初めて接続する場合はSSHキーが生成されます。ターミナル上でパスフレーズを入力して続行します:
173 |
174 | ```
175 | WARNING: The public SSH key file for gcloud does not exist.
176 | WARNING: The private SSH key file for gcloud does not exist.
177 | WARNING: You do not have an SSH key for gcloud.
178 | WARNING: SSH keygen will be executed to generate a key.
179 | Generating public/private rsa key pair.
180 | Enter passphrase (empty for no passphrase):
181 | Enter same passphrase again:
182 | ```
183 |
184 | この時点で生成されたSSHキーがアップロードされ、GCPのプロジェクトに保存されます::
185 |
186 | ```
187 | Your identification has been saved in /home/$USER/.ssh/google_compute_engine.
188 | Your public key has been saved in /home/$USER/.ssh/google_compute_engine.pub.
189 | The key fingerprint is:
190 | SHA256:nz1i8jHmgQuGt+WscqP5SeIaSy5wyIJeL71MuV+QruE $USER@$HOSTNAME
191 | The key's randomart image is:
192 | +---[RSA 2048]----+
193 | | |
194 | | |
195 | | |
196 | | . |
197 | |o. oS |
198 | |=... .o .o o |
199 | |+.+ =+=.+.X o |
200 | |.+ ==O*B.B = . |
201 | | .+.=EB++ o |
202 | +----[SHA256]-----+
203 | Updating project ssh metadata...-Updated [https://www.googleapis.com/compute/v1/projects/$PROJECT_ID].
204 | Updating project ssh metadata...done.
205 | Waiting for SSH key to propagate.
206 | ```
207 |
208 | SSHキーが更新されると`controller-0`インスタンスにログインします:
209 |
210 | ```
211 | Welcome to Ubuntu 20.04.2 LTS (GNU/Linux 5.4.0-1042-gcp x86_64)
212 | ...
213 | ```
214 |
215 | ターミナルで`exit`と入力し、`controller-0`インスタンスを終了します:
216 |
217 | ```
218 | $USER@controller-0:~$ exit
219 | ```
220 | > 出力結果
221 |
222 | ```
223 | logout
224 | Connection to XX.XX.XX.XXX closed
225 | ```
226 |
227 | Next: [CA証明書のプロビジョニングとTLS証明書の生成](04-certificate-authority.md)
228 |
--------------------------------------------------------------------------------
/docs/04-certificate-authority.md:
--------------------------------------------------------------------------------
1 | # CA証明書のプロビジョニングとTLS証明書の生成
2 |
3 | 本実習では、CloudFlareのPKIツールキットである[cfssl](https://github.com/cloudflare/cfssl)を使用して[公開鍵基盤](https://ja.wikipedia.org/wiki/%E5%85%AC%E9%96%8B%E9%8D%B5%E5%9F%BA%E7%9B%A4)をプロビジョニングし、それを使用して認証機関を起動し、etcd、kube-apiserver、kube-controller-manager、kube-scheduler、kubelet、kube-proxyの各コンポーネントのTLS証明書を生成します。
4 |
5 | ## Certificate Authority
6 |
7 | 本セクションでは、追加のTLS証明書を生成するために使用できる認証局をプロビジョニングします。
8 |
9 | CA構成ファイル、証明書、および秘密鍵を生成します:
10 |
11 | ```sh
12 | {
13 |
14 | cat > ca-config.json < ca-csr.json < admin-csr.json <`で識別するクレデンシャルを使用する必要があります。本セクションでは、各Kubernetesワーカーノード用にNode Authorizerの要件を満たす証明書を作成します。
111 |
112 | 各ワーカーノード用の証明書と秘密鍵を生成します:
113 |
114 | ```sh
115 | for instance in worker-{0..2}; do
116 | cat > ${instance}-csr.json < kube-controller-manager-csr.json < kube-proxy-csr.json < kube-scheduler-csr.json < kubernetes-csr.json < KubernetesのAPIサーバーには自動的にKubernetesの内部DNS名が割り当てられます。この名前は、[コントロールプレーンのブートストラップ](08-bootstrapping-kubernetes-controllers.md#configure-the-kubernetes-api-server)で内部クラスタサービス用に予約されたアドレス範囲(`10.32.0.0/24`)の最初のIPアドレス(`10.32.0.1`)にリンクされます。
339 |
340 | 結果:
341 |
342 | ```
343 | kubernetes-key.pem
344 | kubernetes.pem
345 | ```
346 |
347 | ## サービスアカウントのキーペア
348 |
349 | Kubernetesのコントローラーマネージャーは、[サービスアカウントの管理](https://kubernetes.io/docs/admin/service-accounts-admin/)に関するドキュメントで説明されているように、キーペアを使用してサービスアカウントトークンを生成して署名します。
350 |
351 | `service-account`用クライアント証明書と秘密鍵を生成します:
352 |
353 | ```sh
354 | {
355 |
356 | cat > service-account-csr.json <`kube-proxy`、`kube-controller-manager`、`kube-scheduler`、および`kubelet`用クライアント証明書は、次の実習でクライアントの認証用設定ファイルを生成するために使用します。
413 |
414 | Next: [認証用Kubernetes設定ファイルの生成](05-kubernetes-configuration-files.md)
415 |
--------------------------------------------------------------------------------
/docs/05-kubernetes-configuration-files.md:
--------------------------------------------------------------------------------
1 | # 認証用Kubernetes設定ファイルの生成
2 |
3 | 本実習では[Kubernetesのコンフィグファイル](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/)(kubeconfigとも呼ばれます)を生成します。これにより、KubernetesクライアントがKubernetesのAPIサーバーを特定して認証できるようになります。
4 |
5 | ## クライアント認証コンフィグ
6 |
7 | 本セクションでは、`controller manager`、`kubelet`、`kube-proxy`、および`scheduler`のクライアントと`admin`ユーザー用のkubeconfigファイルを生成します。
8 |
9 | ### Kubernetesの公開IPアドレス
10 |
11 | kubeconfigには接続先のKubernetes APIサーバーが必要です。高可用性をサポートするために、Kubernetes APIサーバの前面に配置した外部ロードバランサに割り当てられたIPアドレスが使用されます。
12 |
13 | 静的IPアドレス`kubernetes-the-hard-way`を取得します:
14 |
15 | ```
16 | KUBERNETES_PUBLIC_ADDRESS=$(gcloud compute addresses describe kubernetes-the-hard-way \
17 | --region $(gcloud config get-value compute/region) \
18 | --format 'value(address)')
19 | ```
20 |
21 | ### kubelet用Kubernetesコンフィグファイル
22 |
23 | kubelet用のkubeconfigファイルを生成する際、kubeletのノード名に一致するクライアント証明書を使用する必要があります。これにより、kubeletがKubernetes [Node Authorizer](https://kubernetes.io/docs/admin/authorization/node/)によって適切に許可されます。
24 |
25 | > 次のコマンドは、[TLS証明書の生成](04-certificate-authority.md)でSSL証明書を生成するときに使用したディレクトリと同じディレクトリで実行する必要があります。
26 |
27 | 各ワーカーノード用kubeconfigファイルを生成します:
28 |
29 | ```sh
30 | for instance in worker-{0..2}; do
31 | kubectl config set-cluster kubernetes-the-hard-way \
32 | --certificate-authority=ca.pem \
33 | --embed-certs=true \
34 | --server=https://${KUBERNETES_PUBLIC_ADDRESS}:6443 \
35 | --kubeconfig=${instance}.kubeconfig
36 |
37 | kubectl config set-credentials system:node:${instance} \
38 | --client-certificate=${instance}.pem \
39 | --client-key=${instance}-key.pem \
40 | --embed-certs=true \
41 | --kubeconfig=${instance}.kubeconfig
42 |
43 | kubectl config set-context default \
44 | --cluster=kubernetes-the-hard-way \
45 | --user=system:node:${instance} \
46 | --kubeconfig=${instance}.kubeconfig
47 |
48 | kubectl config use-context default --kubeconfig=${instance}.kubeconfig
49 | done
50 | ```
51 |
52 | 結果:
53 |
54 | ```
55 | worker-0.kubeconfig
56 | worker-1.kubeconfig
57 | worker-2.kubeconfig
58 | ```
59 |
60 | ### kube-proxy用Kubernetesコンフィグファイル
61 |
62 | `kube-proxy`サービス用kubeconfigファイルを生成します:
63 |
64 | ```
65 | {
66 | kubectl config set-cluster kubernetes-the-hard-way \
67 | --certificate-authority=ca.pem \
68 | --embed-certs=true \
69 | --server=https://${KUBERNETES_PUBLIC_ADDRESS}:6443 \
70 | --kubeconfig=kube-proxy.kubeconfig
71 |
72 | kubectl config set-credentials system:kube-proxy \
73 | --client-certificate=kube-proxy.pem \
74 | --client-key=kube-proxy-key.pem \
75 | --embed-certs=true \
76 | --kubeconfig=kube-proxy.kubeconfig
77 |
78 | kubectl config set-context default \
79 | --cluster=kubernetes-the-hard-way \
80 | --user=system:kube-proxy \
81 | --kubeconfig=kube-proxy.kubeconfig
82 |
83 | kubectl config use-context default --kubeconfig=kube-proxy.kubeconfig
84 | }
85 | ```
86 |
87 | 結果:
88 |
89 | ```
90 | kube-proxy.kubeconfig
91 | ```
92 |
93 | ### kube-controller-manager用Kubernetesコンフィグファイル
94 |
95 | `kube-controller-manager`サービス用kubeconfigファイルを生成します:
96 |
97 | ```
98 | {
99 | kubectl config set-cluster kubernetes-the-hard-way \
100 | --certificate-authority=ca.pem \
101 | --embed-certs=true \
102 | --server=https://127.0.0.1:6443 \
103 | --kubeconfig=kube-controller-manager.kubeconfig
104 |
105 | kubectl config set-credentials system:kube-controller-manager \
106 | --client-certificate=kube-controller-manager.pem \
107 | --client-key=kube-controller-manager-key.pem \
108 | --embed-certs=true \
109 | --kubeconfig=kube-controller-manager.kubeconfig
110 |
111 | kubectl config set-context default \
112 | --cluster=kubernetes-the-hard-way \
113 | --user=system:kube-controller-manager \
114 | --kubeconfig=kube-controller-manager.kubeconfig
115 |
116 | kubectl config use-context default --kubeconfig=kube-controller-manager.kubeconfig
117 | }
118 | ```
119 |
120 | 結果:
121 |
122 | ```
123 | kube-controller-manager.kubeconfig
124 | ```
125 |
126 |
127 | ### kube-scheduler用Kubernetesコンフィグファイル
128 |
129 | `kube-scheduler`サービス用kubeconfigファイルを生成します:
130 |
131 | ```
132 | {
133 | kubectl config set-cluster kubernetes-the-hard-way \
134 | --certificate-authority=ca.pem \
135 | --embed-certs=true \
136 | --server=https://127.0.0.1:6443 \
137 | --kubeconfig=kube-scheduler.kubeconfig
138 |
139 | kubectl config set-credentials system:kube-scheduler \
140 | --client-certificate=kube-scheduler.pem \
141 | --client-key=kube-scheduler-key.pem \
142 | --embed-certs=true \
143 | --kubeconfig=kube-scheduler.kubeconfig
144 |
145 | kubectl config set-context default \
146 | --cluster=kubernetes-the-hard-way \
147 | --user=system:kube-scheduler \
148 | --kubeconfig=kube-scheduler.kubeconfig
149 |
150 | kubectl config use-context default --kubeconfig=kube-scheduler.kubeconfig
151 | }
152 | ```
153 |
154 | 結果:
155 |
156 | ```
157 | kube-scheduler.kubeconfig
158 | ```
159 |
160 | ### admin用Kubernetesコンフィグファイル
161 |
162 | `admin`ユーザー用kubeconfigファイルを生成します:
163 |
164 | ```
165 | {
166 | kubectl config set-cluster kubernetes-the-hard-way \
167 | --certificate-authority=ca.pem \
168 | --embed-certs=true \
169 | --server=https://127.0.0.1:6443 \
170 | --kubeconfig=admin.kubeconfig
171 |
172 | kubectl config set-credentials admin \
173 | --client-certificate=admin.pem \
174 | --client-key=admin-key.pem \
175 | --embed-certs=true \
176 | --kubeconfig=admin.kubeconfig
177 |
178 | kubectl config set-context default \
179 | --cluster=kubernetes-the-hard-way \
180 | --user=admin \
181 | --kubeconfig=admin.kubeconfig
182 |
183 | kubectl config use-context default --kubeconfig=admin.kubeconfig
184 | }
185 | ```
186 |
187 | 結果:
188 |
189 | ```
190 | admin.kubeconfig
191 | ```
192 |
193 | ## Kubernetesコンフィグファイルの配布
194 |
195 | 適切な`kubelet`及び`kube-proxy`用kubeconfigファイルを各ワーカーノード用インスタンスにコピーします:
196 |
197 | ```sh
198 | for instance in worker-{0..2}; do
199 | gcloud compute scp ${instance}.kubeconfig kube-proxy.kubeconfig ${instance}:~/
200 | done
201 | ```
202 |
203 | 適切な`kube-controller-manager`及び`kube-scheduler`用kubeconfigファイルをコントロールプレーン用インスタンスにコピーします:
204 |
205 | ```sh
206 | for instance in controller-{0..2}; do
207 | gcloud compute scp admin.kubeconfig kube-controller-manager.kubeconfig kube-scheduler.kubeconfig ${instance}:~/
208 | done
209 | ```
210 |
211 | Next: [データ暗号化の設定とキーの生成](06-data-encryption-keys.md)
212 |
--------------------------------------------------------------------------------
/docs/06-data-encryption-keys.md:
--------------------------------------------------------------------------------
1 | # データ暗号化の設定とキーの生成
2 |
3 | Kubernetesはクラスタの状態、アプリケーションの構成、機密情報など、さまざまなデータを保存します。Kubernetesはクラスタデータを[暗号化](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data)する機能をサポートします。
4 |
5 | 本実習では、Kubernetes Secretsの暗号化に適したキーと[コンフィグ](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/#understanding-the-encryption-at-rest-configuration)を生成します。
6 |
7 | ## 暗号化キー
8 |
9 | 暗号化キーを生成します:
10 |
11 | ```sh
12 | ENCRYPTION_KEY=$(head -c 32 /dev/urandom | base64)
13 | ```
14 |
15 | ## 暗号化コンフィグファイル
16 |
17 | `encryption-config.yaml`という名前の暗号化コンフィグファイルを生成します:
18 |
19 | ```sh
20 | cat > encryption-config.yaml < 上記のコマンドは各コントローラノード`controller-0`、`controller-1`、`controller-2`にて忘れずに実行してください。
107 |
108 | ## 検証
109 |
110 | etcdのクラスターメンバーの一覧を表示します:
111 |
112 | ```
113 | sudo ETCDCTL_API=3 etcdctl member list \
114 | --endpoints=https://127.0.0.1:2379 \
115 | --cacert=/etc/etcd/ca.pem \
116 | --cert=/etc/etcd/kubernetes.pem \
117 | --key=/etc/etcd/kubernetes-key.pem
118 | ```
119 |
120 | > 出力結果
121 |
122 | ```
123 | 3a57933972cb5131, started, controller-2, https://10.240.0.12:2380, https://10.240.0.12:2379, false
124 | f98dc20bce6225a0, started, controller-0, https://10.240.0.10:2380, https://10.240.0.10:2379, false
125 | ffed16798470cab5, started, controller-1, https://10.240.0.11:2380, https://10.240.0.11:2379, false
126 | ```
127 |
128 | Next: [Kubernetesコントロールプレーンのブートストラップ](08-bootstrapping-kubernetes-controllers.md)
129 |
--------------------------------------------------------------------------------
/docs/08-bootstrapping-kubernetes-controllers.md:
--------------------------------------------------------------------------------
1 | # Kubernetesコントロールプレーンのブートストラップ
2 |
3 | 本実習では、3つのインスタンスでコントロールプレーンをブートストラップして可用性の高い構成を実現します。また、KubernetesのAPIサーバーをリモートクライアントに公開する外部ロードバランサも作成します。各ノードには、Kubernetes API Server、Scheduler、Controller Managerの各コンポーネントがインストールされます。
4 |
5 | ## 前提条件
6 |
7 | 本実習のコマンドは`controller-0`、`controller-1`、`controller-2`の各コントロールプレーン用インスタンスで実行する必要があります。`gcloud`コマンドを使用して各コントローラインスタンスにログインします。例:
8 |
9 | ```
10 | gcloud compute ssh controller-0
11 | ```
12 |
13 | ### tmuxを使った並列なコマンド実行
14 |
15 | [tmux](https://github.com/tmux/tmux/wiki)を使用すると複数のインスタンスで同時にコマンドを実行できます。前提条件の[tmuxを使った並列なコマンド実行](01-prerequisites.md#tmuxを使った並列なコマンド実行)セクションを参照してください。
16 |
17 | ## Kubernetesコントロールプレーンのプロビジョニング
18 |
19 | Kubenretesのコンフィグ用ディレクトリを作成します:
20 |
21 | ```
22 | sudo mkdir -p /etc/kubernetes/config
23 | ```
24 |
25 | ### Kubernetesコントローラー用バイナリーのダウンロードとインストール
26 |
27 | Kubernetesの公式リリースバイナリーをダウンロードします:
28 |
29 | ```
30 | wget -q --show-progress --https-only --timestamping \
31 | "https://storage.googleapis.com/kubernetes-release/release/v1.21.0/bin/linux/amd64/kube-apiserver" \
32 | "https://storage.googleapis.com/kubernetes-release/release/v1.21.0/bin/linux/amd64/kube-controller-manager" \
33 | "https://storage.googleapis.com/kubernetes-release/release/v1.21.0/bin/linux/amd64/kube-scheduler" \
34 | "https://storage.googleapis.com/kubernetes-release/release/v1.21.0/bin/linux/amd64/kubectl"
35 | ```
36 |
37 | Kubernetesバイナリーをインストールします:
38 |
39 | ```
40 | {
41 | chmod +x kube-apiserver kube-controller-manager kube-scheduler kubectl
42 | sudo mv kube-apiserver kube-controller-manager kube-scheduler kubectl /usr/local/bin/
43 | }
44 | ```
45 |
46 | ### Kubernetes APIサーバーの設定
47 |
48 | ```
49 | {
50 | sudo mkdir -p /var/lib/kubernetes/
51 |
52 | sudo mv ca.pem ca-key.pem kubernetes-key.pem kubernetes.pem \
53 | service-account-key.pem service-account.pem \
54 | encryption-config.yaml /var/lib/kubernetes/
55 | }
56 | ```
57 |
58 | クラスターのメンバーにAPIサーバーを通知するためにインスタンスの内部IPアドレスが使用されます。以下のコマンドで現在作業中のインスタンスが持つ内部IPアドレスを取得します:
59 |
60 | ```
61 | INTERNAL_IP=$(curl -s -H "Metadata-Flavor: Google" \
62 | http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/ip)
63 | ```
64 |
65 | ```
66 | REGION=$(curl -s -H "Metadata-Flavor: Google" \
67 | http://metadata.google.internal/computeMetadata/v1/project/attributes/google-compute-default-region)
68 | ```
69 |
70 | ```
71 | KUBERNETES_PUBLIC_ADDRESS=$(gcloud compute addresses describe kubernetes-the-hard-way \
72 | --region $REGION \
73 | --format 'value(address)')
74 | ```
75 |
76 | systemdユニットファイル`kube-apiserver.service`を作成します:
77 |
78 | ```sh
79 | cat < KubernetesのAPIサーバーが完全に初期化されるまでには最大10秒かかります。
213 |
214 | ### HTTPのヘルスチェックを有効化
215 |
216 | [Google Network Load Balancer](https://cloud.google.com/compute/docs/load-balancing/network)を使用して3つのAPIサーバーにトラフィックを分散し、各APIサーバーがTLS接続を終端してクライアント証明書を検証できるようにします。ネットワークロードバランサーは、HTTPヘルスチェックのみをサポートします。つまり、APIサーバーによって公開されたHTTPSエンドポイントは使用できません。回避策として、nginxを使用してHTTPのヘルスチェックをプロキシすることができます。本セクションではnginxをインストールし、ポート`80`でHTTPヘルスチェックを受け入れ、`https://127.0.0.1:6443/healthz` 上のAPIサーバへの接続をプロキシするように設定します。
217 |
218 | > APIサーバーエンドポイント`/healthz`は、デフォルトで認証を必要としません。
219 |
220 | HTTPヘルスチェックを処理するために基本的なWebサーバーをインストールします:
221 |
222 | ```
223 | sudo apt-get update
224 | sudo apt-get install -y nginx
225 | ```
226 |
227 | ```sh
228 | cat > kubernetes.default.svc.cluster.local < 上記のコマンドは各コントローラノード`controller-0`、`controller-1`、`controller-2`にて忘れずに実行してください。
290 |
291 | ## RBACを使ったKubeletの認可
292 |
293 | 本セクションでは、RBACのアクセス権を設定して、KubernetesのAPIサーバーが各ワーカーノード上のKubeletにアクセスできるようにします。メトリクスやログを取得したり、Pod内でコマンドを実行するためにはKubelet APIへのアクセスが必要です。
294 |
295 | > 本チュートリアルでは、Kubeletの`--authorization-mode`フラグを`Webhook`に設定します。Webhookモードでは、[SubjectAccessReview](https://kubernetes.io/docs/admin/authorization/#checking-api-access) APIを使用して認可を判定します。
296 |
297 | 本セクションのコマンドはクラスター全体に影響するため、1つのコントローラーノードから1回実行するだけで大丈夫です。
298 |
299 | ```
300 | gcloud compute ssh controller-0
301 | ```
302 |
303 | `system:kube-apiserver-to-kubelet`という名前の[ClusterRole](https://kubernetes.io/docs/admin/authorization/rbac/#role-and-clusterrole)を作成し、Kubelet APIにアクセスしたり、Podの管理に関連する一般的なタスクを実行したりするための権限を付与します:
304 |
305 | ```sh
306 | cat < 本チュートリアルで作成したインスタンスには、本セクションを完了する権限がありません。**インスタンスの作成に使用したのと同じ作業マシンから次のコマンドを実行します**。
356 |
357 | ### ネットワークロードバランサーのプロビジョニング
358 |
359 | 外部ロードバランサーネットワークリソースを作成します:
360 |
361 | ```sh
362 | {
363 | KUBERNETES_PUBLIC_ADDRESS=$(gcloud compute addresses describe kubernetes-the-hard-way \
364 | --region $(gcloud config get-value compute/region) \
365 | --format 'value(address)')
366 |
367 | gcloud compute http-health-checks create kubernetes \
368 | --description "Kubernetes Health Check" \
369 | --host "kubernetes.default.svc.cluster.local" \
370 | --request-path "/healthz"
371 |
372 | gcloud compute firewall-rules create kubernetes-the-hard-way-allow-health-check \
373 | --network kubernetes-the-hard-way \
374 | --source-ranges 209.85.152.0/22,209.85.204.0/22,35.191.0.0/16 \
375 | --allow tcp
376 |
377 | gcloud compute target-pools create kubernetes-target-pool \
378 | --http-health-check kubernetes
379 |
380 | gcloud compute target-pools add-instances kubernetes-target-pool \
381 | --instances controller-0,controller-1,controller-2
382 |
383 | gcloud compute forwarding-rules create kubernetes-forwarding-rule \
384 | --address ${KUBERNETES_PUBLIC_ADDRESS} \
385 | --ports 6443 \
386 | --region $(gcloud config get-value compute/region) \
387 | --target-pool kubernetes-target-pool
388 | }
389 | ```
390 |
391 | ### 検証
392 |
393 | > 本チュートリアルで作成したインスタンスには、本セクションを完了する権限がありません。**インスタンスの作成に使用したのと同じ作業マシンから次のコマンドを実行します**。
394 |
395 | 静的IPアドレス`kubernetes-the-hard-way`を取得します:
396 |
397 | ```
398 | KUBERNETES_PUBLIC_ADDRESS=$(gcloud compute addresses describe kubernetes-the-hard-way \
399 | --region $(gcloud config get-value compute/region) \
400 | --format 'value(address)')
401 | ```
402 |
403 | Kubernetesのバージョン情報を取得するHTTPリクエストを発行します:
404 |
405 | ```
406 | curl --cacert ca.pem https://${KUBERNETES_PUBLIC_ADDRESS}:6443/version
407 | ```
408 |
409 | > 出力結果
410 |
411 | ```json
412 | {
413 | "major": "1",
414 | "minor": "21",
415 | "gitVersion": "v1.21.0",
416 | "gitCommit": "cb303e613a121a29364f75cc67d3d580833a7479",
417 | "gitTreeState": "clean",
418 | "buildDate": "2021-04-08T16:25:06Z",
419 | "goVersion": "go1.16.1",
420 | "compiler": "gc",
421 | "platform": "linux/amd64"
422 | }
423 | ```
424 |
425 | Next: [Kubenretesワーカーノードのブートストラップ](09-bootstrapping-kubernetes-workers.md)
426 |
--------------------------------------------------------------------------------
/docs/09-bootstrapping-kubernetes-workers.md:
--------------------------------------------------------------------------------
1 | # Kubenretesワーカーノードのブートストラップ
2 |
3 |
4 |
5 | 本実習では、3つのKubernetesワーカーノードをブートストラップします。各ノードには[runc](https://github.com/opencontainers/runc)、[CNI](https://github.com/containernetworking/cni), [containerd](https://github.com/containerd/containerd)、[kubelet](https://kubernetes.io/docs/admin/kubelet)および[kube-proxy](https://kubernetes.io/docs/concepts/cluster-administration/proxies)がインストールされます。
6 |
7 | ## 前提条件
8 |
9 | 本実習のコマンドは`worker-0`, `worker-1`, and `worker-2`の各ワーカーノード用インスタンスで実行する必要があります。`gcloud`コマンドを使用して各コントローラインスタンスにログインします。例:
10 |
11 | ```
12 | gcloud compute ssh worker-0
13 | ```
14 |
15 | ### tmuxを使った並列なコマンド実行
16 |
17 | [tmux](https://github.com/tmux/tmux/wiki)を使用すると複数のインスタンスで同時にコマンドを実行できます。前提条件の[tmuxを使った並列なコマンド実行](01-prerequisites.md#tmuxを使った並列なコマンド実行)セクションを参照してください。
18 |
19 | ## 単一Kubernetesワーカーノードのプロビジョニング
20 |
21 | OSの依存ライブラリをインストールします:
22 |
23 | ```
24 | {
25 | sudo apt-get update
26 | sudo apt-get -y install socat conntrack ipset
27 | }
28 | ```
29 |
30 | > socatバイナリーは`kubectl port-forward`コマンドのサポートを有効にします。
31 |
32 | ### Swapの無効化
33 |
34 | デフォルトで[swap](https://help.ubuntu.com/community/SwapFaq)が有効になっている場合、kubeletの起動は失敗します。Kubernetesが適切なリソース割り当てとサービス品質を提供できるように、swapを無効にすることを[推奨](https://github.com/kubernetes/kubernetes/issues/7294)します。
35 |
36 | swapが有効になっているか確認します:
37 |
38 | ```
39 | sudo swapon --show
40 | ```
41 |
42 | 出力が空の場合、swapは有効になっていません。有効になっている場合は、次のコマンドを実行してただちに無効にします:
43 |
44 | ```
45 | sudo swapoff -a
46 | ```
47 |
48 | > インスタンスの再起動後もswapがオフのままになるようにするには、Linuxディストリビューションのドキュメントを参照してください。
49 |
50 | ### ワーカーバイナリーのダウンロードとインストール
51 |
52 | ```
53 | wget -q --show-progress --https-only --timestamping \
54 | https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.21.0/crictl-v1.21.0-linux-amd64.tar.gz \
55 | https://github.com/opencontainers/runc/releases/download/v1.0.0-rc93/runc.amd64 \
56 | https://github.com/containernetworking/plugins/releases/download/v0.9.1/cni-plugins-linux-amd64-v0.9.1.tgz \
57 | https://github.com/containerd/containerd/releases/download/v1.4.4/containerd-1.4.4-linux-amd64.tar.gz \
58 | https://storage.googleapis.com/kubernetes-release/release/v1.21.0/bin/linux/amd64/kubectl \
59 | https://storage.googleapis.com/kubernetes-release/release/v1.21.0/bin/linux/amd64/kube-proxy \
60 | https://storage.googleapis.com/kubernetes-release/release/v1.21.0/bin/linux/amd64/kubelet
61 | ```
62 |
63 | インストール用ディレクトリを作成します:
64 |
65 | ```
66 | sudo mkdir -p \
67 | /etc/cni/net.d \
68 | /opt/cni/bin \
69 | /var/lib/kubelet \
70 | /var/lib/kube-proxy \
71 | /var/lib/kubernetes \
72 | /var/run/kubernetes
73 | ```
74 |
75 | ワーカーバイナリーをインストールします:
76 |
77 | ```
78 | {
79 | mkdir containerd
80 | tar -xvf crictl-v1.21.0-linux-amd64.tar.gz
81 | tar -xvf containerd-1.4.4-linux-amd64.tar.gz -C containerd
82 | sudo tar -xvf cni-plugins-linux-amd64-v0.9.1.tgz -C /opt/cni/bin/
83 | sudo mv runc.amd64 runc
84 | chmod +x crictl kubectl kube-proxy kubelet runc
85 | sudo mv crictl kubectl kube-proxy kubelet runc /usr/local/bin/
86 | sudo mv containerd/bin/* /bin/
87 | }
88 | ```
89 |
90 | ### CNIのネットワーク設定
91 |
92 | 現在作業中のインスタンスが持つPodのCIDR範囲を取得します:
93 |
94 | ```
95 | POD_CIDR=$(curl -s -H "Metadata-Flavor: Google" \
96 | http://metadata.google.internal/computeMetadata/v1/instance/attributes/pod-cidr)
97 | ```
98 |
99 | ネットワーク構成ファイル`bridge`を作成します:
100 |
101 | ```sh
102 | cat < `resolvConf`の設定は、`system-resolved`を実行しているシステムのサービスディスカバリにCoreDNSを使用する場合に、ループを回避するために使用されます。
216 |
217 | systemdユニットファイル`kubelet.service`を作成します:
218 |
219 | ```sh
220 | cat < 上記のコマンドは各コントローラノード`worker-0`、`worker-1`、`worker-2`にて忘れずに実行してください。
294 |
295 | ## 検証
296 |
297 | > 本チュートリアルで作成したインスタンスには、本セクションを完了する権限がありません。インスタンスの作成に使用したのと同じ作業マシンから次のコマンドを実行します。
298 |
299 | 登録されたKubernetesのノード一覧を表示します:
300 |
301 | ```
302 | gcloud compute ssh controller-0 \
303 | --command "kubectl get nodes --kubeconfig admin.kubeconfig"
304 | ```
305 |
306 | > 出力結果
307 |
308 | ```
309 | NAME STATUS ROLES AGE VERSION
310 | worker-0 Ready 22s v1.21.0
311 | worker-1 Ready 22s v1.21.0
312 | worker-2 Ready 22s v1.21.0
313 | ```
314 |
315 | Next: [リモートアクセス用のkubectl設定](10-configuring-kubectl.md)
316 |
--------------------------------------------------------------------------------
/docs/10-configuring-kubectl.md:
--------------------------------------------------------------------------------
1 | # リモートアクセス用のkubectl設定
2 |
3 | 本実習では、`admin`ユーザーの認証情報に基づいた`kubectl`コマンド用のkubeconfigファイルを生成します。
4 |
5 | > 本実習で使用するコマンドは、管理クライアント証明書の生成に使用したディレクトリと同じディレクトリから実行してください。
6 |
7 | ## admin用Kubernetesコンフィグファイル
8 |
9 | kubeconfigには接続先のKubernetes APIサーバーが必要です。高可用性をサポートするために、Kubernetes APIサーバの前面に配置した外部ロードバランサに割り当てられたIPアドレスが使用されます。
10 |
11 | `admin`ユーザとして認証するのに適したkubeconfigファイルを生成します:
12 |
13 | ```sh
14 | {
15 | KUBERNETES_PUBLIC_ADDRESS=$(gcloud compute addresses describe kubernetes-the-hard-way \
16 | --region $(gcloud config get-value compute/region) \
17 | --format 'value(address)')
18 |
19 | kubectl config set-cluster kubernetes-the-hard-way \
20 | --certificate-authority=ca.pem \
21 | --embed-certs=true \
22 | --server=https://${KUBERNETES_PUBLIC_ADDRESS}:6443
23 |
24 | kubectl config set-credentials admin \
25 | --client-certificate=admin.pem \
26 | --client-key=admin-key.pem
27 |
28 | kubectl config set-context kubernetes-the-hard-way \
29 | --cluster=kubernetes-the-hard-way \
30 | --user=admin
31 |
32 | kubectl config use-context kubernetes-the-hard-way
33 | }
34 | ```
35 |
36 | ## 検証
37 |
38 | リモートにあるKubernetesクラスターのバージョンを確認します:
39 |
40 | ```
41 | kubectl version
42 | ```
43 |
44 | > 出力結果
45 |
46 | ```
47 | Client Version: version.Info{Major:"1", Minor:"21", GitVersion:"v1.21.0", GitCommit:"cb303e613a121a29364f75cc67d3d580833a7479", GitTreeState:"clean", BuildDate:"2021-04-08T16:31:21Z", GoVersion:"go1.16.1", Compiler:"gc", Platform:"linux/amd64"}
48 | Server Version: version.Info{Major:"1", Minor:"21", GitVersion:"v1.21.0", GitCommit:"cb303e613a121a29364f75cc67d3d580833a7479", GitTreeState:"clean", BuildDate:"2021-04-08T16:25:06Z", GoVersion:"go1.16.1", Compiler:"gc", Platform:"linux/amd64"}
49 | ```
50 |
51 | リモートにあるKubernetesクラスター上にあるノードの一覧を表示します:
52 |
53 | ```
54 | kubectl get nodes
55 | ```
56 |
57 | > 出力結果
58 |
59 | ```
60 | NAME STATUS ROLES AGE VERSION
61 | worker-0 Ready 2m35s v1.21.0
62 | worker-1 Ready 2m35s v1.21.0
63 | worker-2 Ready 2m35s v1.21.0
64 | ```
65 |
66 | Next: [Podが使うネットワーク経路のプロビジョニング](11-pod-network-routes.md)
67 |
--------------------------------------------------------------------------------
/docs/11-pod-network-routes.md:
--------------------------------------------------------------------------------
1 | # Podが使うネットワーク経路のプロビジョニング
2 |
3 | ノードにスケジュールされたPodは、ノードが持つPod CIDR範囲からIPアドレスを受け取ります。この時点ではネットワーク[経路](https://cloud.google.com/compute/docs/vpc/routes)が欠落しているため、Podは異なるノード上で動作している他のPodと通信できません。
4 |
5 | 本実習では、ノードのPod CIDR範囲をノードの内部IPアドレスにマップするための経路を各ワーカーノード上に作成します。
6 |
7 | > Kubernetesのネットワーキングモデルを実装する方法は[他にも](https://kubernetes.io/docs/concepts/cluster-administration/networking/#how-to-achieve-this)あります。
8 |
9 | ## ルーティングテーブル
10 |
11 | ここでは、`kubernetes-the-hard-way`VPCネットワーク上に経路を作成するために必要な情報を収集します。
12 |
13 | 各ワーカーインスタンスの内部IPアドレスとPod CIDR範囲を表示します:
14 |
15 | ```sh
16 | for instance in worker-{0..2}; do
17 | gcloud compute instances describe ${instance} \
18 | --format 'value[separator=" "](networkInterfaces[0].networkIP,metadata.items[0].value)'
19 | done
20 | ```
21 |
22 | > 出力結果
23 |
24 | ```
25 | 10.240.0.20 10.200.0.0/24
26 | 10.240.0.21 10.200.1.0/24
27 | 10.240.0.22 10.200.2.0/24
28 | ```
29 |
30 | ## 経路
31 |
32 | 各ワーカーインスタンス用のネットワーク経路を作成します:
33 |
34 | ```sh
35 | for i in 0 1 2; do
36 | gcloud compute routes create kubernetes-route-10-200-${i}-0-24 \
37 | --network kubernetes-the-hard-way \
38 | --next-hop-address 10.240.0.2${i} \
39 | --destination-range 10.200.${i}.0/24
40 | done
41 | ```
42 |
43 | VPCネットワーク`kubernetes-the-hard-way`内の経路一覧を表示します:
44 |
45 | ```
46 | gcloud compute routes list --filter "network: kubernetes-the-hard-way"
47 | ```
48 |
49 | > 出力結果
50 |
51 | ```
52 | NAME NETWORK DEST_RANGE NEXT_HOP PRIORITY
53 | default-route-1606ba68df692422 kubernetes-the-hard-way 10.240.0.0/24 kubernetes-the-hard-way 0
54 | default-route-615e3652a8b74e4d kubernetes-the-hard-way 0.0.0.0/0 default-internet-gateway 1000
55 | kubernetes-route-10-200-0-0-24 kubernetes-the-hard-way 10.200.0.0/24 10.240.0.20 1000
56 | kubernetes-route-10-200-1-0-24 kubernetes-the-hard-way 10.200.1.0/24 10.240.0.21 1000
57 | kubernetes-route-10-200-2-0-24 kubernetes-the-hard-way 10.200.2.0/24 10.240.0.22 1000
58 | ```
59 |
60 | Next: [DNSクラスターアドオンのデプロイ](12-dns-addon.md)
61 |
--------------------------------------------------------------------------------
/docs/12-dns-addon.md:
--------------------------------------------------------------------------------
1 | # DNSクラスターアドオンのデプロイ
2 |
3 | 本実習では、[CoreDNS](https://coredns.io/)によってサポートされるDNSベースのサービスディスカバリを提供する[アドオン](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/)を、Kubernetesクラスター内で稼働するアプリケーションに導入します。
4 |
5 | ## The DNS Cluster Add-on
6 |
7 | クラスターアドオン`coredns`をデプロイします:
8 |
9 | ```
10 | kubectl apply -f https://storage.googleapis.com/kubernetes-the-hard-way/coredns-1.8.yaml
11 | ```
12 |
13 | > 出力結果
14 |
15 | ```
16 | serviceaccount/coredns created
17 | clusterrole.rbac.authorization.k8s.io/system:coredns created
18 | clusterrolebinding.rbac.authorization.k8s.io/system:coredns created
19 | configmap/coredns created
20 | deployment.apps/coredns created
21 | service/kube-dns created
22 | ```
23 |
24 | Deploymentリソース`kube-dns`によって作られたPodの一覧を表示します:
25 |
26 | ```
27 | kubectl get pods -l k8s-app=kube-dns -n kube-system
28 | ```
29 |
30 | > 出力結果
31 |
32 | ```
33 | NAME READY STATUS RESTARTS AGE
34 | coredns-8494f9c688-hh7r2 1/1 Running 0 10s
35 | coredns-8494f9c688-zqrj2 1/1 Running 0 10s
36 | ```
37 |
38 | ## 検証
39 |
40 | Deploymentリソース`busybox`をデプロイします:
41 |
42 | ```
43 | kubectl run busybox --image=busybox:1.28 --command -- sleep 3600
44 | ```
45 |
46 | Deploymentリソース`busybox`によって作られたPodの一覧を表示します:
47 |
48 | ```
49 | kubectl get pods -l run=busybox
50 | ```
51 |
52 | > 出力結果
53 |
54 | ```
55 | NAME READY STATUS RESTARTS AGE
56 | busybox 1/1 Running 0 3s
57 | ```
58 |
59 | Podリソース`busybox`のフルネームを取得します:
60 |
61 | ```
62 | POD_NAME=$(kubectl get pods -l run=busybox -o jsonpath="{.items[0].metadata.name}")
63 | ```
64 |
65 | `busybox`の中で`kubernetes`のサービスに対するDNSルックアップを実行します:
66 |
67 | ```
68 | kubectl exec -ti $POD_NAME -- nslookup kubernetes
69 | ```
70 |
71 | > 出力結果
72 |
73 | ```
74 | Server: 10.32.0.10
75 | Address 1: 10.32.0.10 kube-dns.kube-system.svc.cluster.local
76 |
77 | Name: kubernetes
78 | Address 1: 10.32.0.1 kubernetes.default.svc.cluster.local
79 | ```
80 |
81 | Next: [スモークテスト](13-smoke-test.md)
82 |
--------------------------------------------------------------------------------
/docs/13-smoke-test.md:
--------------------------------------------------------------------------------
1 | # スモークテスト
2 |
3 | 本実習では、Kubernetesクラスターが正常に機能していることを確認するために必要な一連のタスクを実行します。
4 |
5 | ## データの暗号化
6 |
7 | 本セクションでは、[保存されている秘密データを暗号化する](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/#verifying-that-data-is-encrypted)機能を確認します。
8 |
9 | 一般的なSecretデータを作成する:
10 |
11 | ```
12 | kubectl create secret generic kubernetes-the-hard-way \
13 | --from-literal="mykey=mydata"
14 | ```
15 |
16 | etcdに保存されているsecretデータ`kubernets-the-hard-way`のhexdumpを表示します:
17 |
18 | ```
19 | gcloud compute ssh controller-0 \
20 | --command "sudo ETCDCTL_API=3 etcdctl get \
21 | --endpoints=https://127.0.0.1:2379 \
22 | --cacert=/etc/etcd/ca.pem \
23 | --cert=/etc/etcd/kubernetes.pem \
24 | --key=/etc/etcd/kubernetes-key.pem\
25 | /registry/secrets/default/kubernetes-the-hard-way | hexdump -C"
26 | ```
27 |
28 | > 出力結果
29 |
30 | ```
31 | 00000000 2f 72 65 67 69 73 74 72 79 2f 73 65 63 72 65 74 |/registry/secret|
32 | 00000010 73 2f 64 65 66 61 75 6c 74 2f 6b 75 62 65 72 6e |s/default/kubern|
33 | 00000020 65 74 65 73 2d 74 68 65 2d 68 61 72 64 2d 77 61 |etes-the-hard-wa|
34 | 00000030 79 0a 6b 38 73 3a 65 6e 63 3a 61 65 73 63 62 63 |y.k8s:enc:aescbc|
35 | 00000040 3a 76 31 3a 6b 65 79 31 3a 97 d1 2c cd 89 0d 08 |:v1:key1:..,....|
36 | 00000050 29 3c 7d 19 41 cb ea d7 3d 50 45 88 82 a3 1f 11 |)<}.A...=PE.....|
37 | 00000060 26 cb 43 2e c8 cf 73 7d 34 7e b1 7f 9f 71 d2 51 |&.C...s}4~...q.Q|
38 | 00000070 45 05 16 e9 07 d4 62 af f8 2e 6d 4a cf c8 e8 75 |E.....b...mJ...u|
39 | 00000080 6b 75 1e b7 64 db 7d 7f fd f3 96 62 e2 a7 ce 22 |ku..d.}....b..."|
40 | 00000090 2b 2a 82 01 c3 f5 83 ae 12 8b d5 1d 2e e6 a9 90 |+*..............|
41 | 000000a0 bd f0 23 6c 0c 55 e2 52 18 78 fe bf 6d 76 ea 98 |..#l.U.R.x..mv..|
42 | 000000b0 fc 2c 17 36 e3 40 87 15 25 13 be d6 04 88 68 5b |.,.6.@..%.....h[|
43 | 000000c0 a4 16 81 f6 8e 3b 10 46 cb 2c ba 21 35 0c 5b 49 |.....;.F.,.!5.[I|
44 | 000000d0 e5 27 20 4c b3 8e 6b d0 91 c2 28 f1 cc fa 6a 1b |.' L..k...(...j.|
45 | 000000e0 31 19 74 e7 a5 66 6a 99 1c 84 c7 e0 b0 fc 32 86 |1.t..fj.......2.|
46 | 000000f0 f3 29 5a a4 1c d5 a4 e3 63 26 90 95 1e 27 d0 14 |.)Z.....c&...'..|
47 | 00000100 94 f0 ac 1a cd 0d b9 4b ae 32 02 a0 f8 b7 3f 0b |.......K.2....?.|
48 | 00000110 6f ad 1f 4d 15 8a d6 68 95 63 cf 7d 04 9a 52 71 |o..M...h.c.}..Rq|
49 | 00000120 75 ff 87 6b c5 42 e1 72 27 b5 e9 1a fe e8 c0 3f |u..k.B.r'......?|
50 | 00000130 d9 04 5e eb 5d 43 0d 90 ce fa 04 a8 4a b0 aa 01 |..^.]C......J...|
51 | 00000140 cf 6d 5b 80 70 5b 99 3c d6 5c c0 dc d1 f5 52 4a |.m[.p[.<.\....RJ|
52 | 00000150 2c 2d 28 5a 63 57 8e 4f df 0a |,-(ZcW.O..|
53 | 0000015a
54 | ```
55 |
56 | etcd上のキーのプレフィックスには`k8s:enc:aescbc:v1:key1`が付いているはずです。これは、`aescbc`プロバイダが暗号化されたキー`key1`のデータを暗号化するために使用されたことを示します。
57 |
58 | ## Deployment
59 |
60 | 本セクションでは、[Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)を作成および管理する機能を確認します。
61 |
62 | [nginx](https://nginx.org/en/)のDeploymentを作成します:
63 |
64 | ```
65 | kubectl create deployment nginx --image=nginx
66 | ```
67 |
68 | Deploymentリソース`nginx`によって作られたPodの一覧を表示します:
69 |
70 | ```
71 | kubectl get pods -l app=nginx
72 | ```
73 |
74 | > 出力結果
75 |
76 | ```
77 | NAME READY STATUS RESTARTS AGE
78 | nginx-f89759699-kpn5m 1/1 Running 0 10s
79 | ```
80 |
81 | ### ポート転送
82 |
83 | 本セクションでは、[ポート転送](https://kubernetes.io/docs/tasks/access-application-cluster/port-forward-access-application-cluster/)を使用してアプリケーションにリモートでアクセスする機能を確認します。
84 |
85 | Podリソース`nginx`のフルネームを取得します:
86 |
87 | ```
88 | POD_NAME=$(kubectl get pods -l app=nginx -o jsonpath="{.items[0].metadata.name}")
89 | ```
90 |
91 | `nginx`Podの`80`番ポートを、手元のマシンの`8080`番ポートに転送します:
92 |
93 | ```sh
94 | kubectl port-forward $POD_NAME 8080:80
95 | ```
96 |
97 | > 出力結果
98 |
99 | ```
100 | Forwarding from 127.0.0.1:8080 -> 80
101 | Forwarding from [::1]:8080 -> 80
102 | ```
103 |
104 | 新しいターミナルを開き、転送済アドレスを使ってHTTPリクエストを発行します:
105 |
106 | ```
107 | curl --head http://127.0.0.1:8080
108 | ```
109 |
110 | > 出力結果
111 |
112 | ```
113 | HTTP/1.1 200 OK
114 | Server: nginx/1.19.10
115 | Date: Sun, 02 May 2021 05:29:25 GMT
116 | Content-Type: text/html
117 | Content-Length: 612
118 | Last-Modified: Tue, 13 Apr 2021 15:13:59 GMT
119 | Connection: keep-alive
120 | ETag: "6075b537-264"
121 | Accept-Ranges: bytes
122 | ```
123 |
124 | 前のターミナルに戻り、`nginx`Podへのポート転送を停止します:
125 |
126 | ```
127 | Forwarding from 127.0.0.1:8080 -> 80
128 | Forwarding from [::1]:8080 -> 80
129 | Handling connection for 8080
130 | ^C
131 | ```
132 |
133 | ### ログ
134 |
135 | 本セクションでは、[コンテナのログを取得](https://kubernetes.io/docs/concepts/cluster-administration/logging/)する機能を確認します。
136 |
137 | `nginx`Podのログを表示します:
138 |
139 | ```sh
140 | kubectl logs $POD_NAME
141 | ```
142 |
143 | > 出力結果
144 |
145 | ```
146 | ...
147 | 127.0.0.1 - - [02/May/2021:05:29:25 +0000] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.64.0" "-"
148 | ```
149 |
150 | ### コマンドの実行
151 |
152 | 本セクションでは、[コンテナ内でコマンドが実行できる](https://kubernetes.io/docs/tasks/debug-application-cluster/get-shell-running-container/#running-individual-commands-in-a-container)ことを確認します。
153 |
154 | `nginx`コンテナで`nginx-v`コマンドを実行して、nginxバージョンを表示します:
155 |
156 | ```sh
157 | kubectl exec -ti $POD_NAME -- nginx -v
158 | ```
159 |
160 | > 出力結果
161 |
162 | ```
163 | nginx version: nginx/1.19.10
164 | ```
165 |
166 | ## サービス
167 |
168 | 本セクションでは、[サービス](https://kubernetes.io/docs/concepts/services-networking/service/)を使用してアプリケーションを公開する機能を確認します。
169 |
170 | [NodePort](https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport)サービスを使用して`nginx`のDeploymentを公開します。
171 |
172 | ```
173 | kubectl expose deployment nginx --port 80 --type NodePort
174 | ```
175 |
176 | >クラスターが[クラウドプロバイダーインテグレーション](https://kubernetes.io/docs/getting-started-guides/scratch/#cloud-provider)で構成されていないため、サービスのtype:LoadBalancerを使用できません。クラウドプロバイダーインテグレーションのセットアップについては本チュートリアルの対象外です。
177 |
178 | `nginx`サービスに割り当てられたノード上のポートを取得します:
179 |
180 | ```
181 | NODE_PORT=$(kubectl get svc nginx \
182 | --output=jsonpath='{range .spec.ports[0]}{.nodePort}')
183 | ```
184 |
185 | `nginx`のノードポートへのアクセスを許可するファイアウォールルールを作成します:
186 |
187 | ```sh
188 | gcloud compute firewall-rules create kubernetes-the-hard-way-allow-nginx-service \
189 | --allow=tcp:${NODE_PORT} \
190 | --network kubernetes-the-hard-way
191 | ```
192 |
193 | ワーカーインスタンスの外部IPアドレスを取得します:
194 |
195 | ```
196 | EXTERNAL_IP=$(gcloud compute instances describe worker-0 \
197 | --format 'value(networkInterfaces[0].accessConfigs[0].natIP)')
198 | ```
199 |
200 | 取得した外部IPアドレスと`nginx`のノードポートを使ってHTTPリクエストを発行します:
201 |
202 | ```sh
203 | curl -I http://${EXTERNAL_IP}:${NODE_PORT}
204 | ```
205 |
206 | > 出力結果
207 |
208 | ```
209 | HTTP/1.1 200 OK
210 | Server: nginx/1.19.10
211 | Date: Sun, 02 May 2021 05:31:52 GMT
212 | Content-Type: text/html
213 | Content-Length: 612
214 | Last-Modified: Tue, 13 Apr 2021 15:13:59 GMT
215 | Connection: keep-alive
216 | ETag: "6075b537-264"
217 | Accept-Ranges: bytes
218 | ```
219 |
220 | Next: [お掃除](14-cleanup.md)
221 |
--------------------------------------------------------------------------------
/docs/14-cleanup.md:
--------------------------------------------------------------------------------
1 | # お掃除
2 |
3 | 本実習では、チュートリアルで作成した計算資源を削除します。
4 |
5 | ## Compute Instances
6 |
7 | コントロールプレーン及びワーカーノード用に作成したインスタンスを削除します:
8 |
9 | ```
10 | gcloud -q compute instances delete \
11 | controller-0 controller-1 controller-2 \
12 | worker-0 worker-1 worker-2 \
13 | --zone $(gcloud config get-value compute/zone)
14 | ```
15 |
16 | ## ネットワーク
17 |
18 | 外部ロードバランサーリソースを削除します:
19 |
20 | ```
21 | {
22 | gcloud -q compute forwarding-rules delete kubernetes-forwarding-rule \
23 | --region $(gcloud config get-value compute/region)
24 |
25 | gcloud -q compute target-pools delete kubernetes-target-pool
26 |
27 | gcloud -q compute http-health-checks delete kubernetes
28 |
29 | gcloud -q compute addresses delete kubernetes-the-hard-way
30 | }
31 | ```
32 |
33 | ファイアウォールルール`kubernetes-the-hard-way`を削除します:
34 |
35 | ```
36 | gcloud -q compute firewall-rules delete \
37 | kubernetes-the-hard-way-allow-nginx-service \
38 | kubernetes-the-hard-way-allow-internal \
39 | kubernetes-the-hard-way-allow-external \
40 | kubernetes-the-hard-way-allow-health-check
41 | ```
42 |
43 | ネットワークVPC`kubernetes-the-hard-way`を削除します:
44 |
45 | ```
46 | {
47 | gcloud -q compute routes delete \
48 | kubernetes-route-10-200-0-0-24 \
49 | kubernetes-route-10-200-1-0-24 \
50 | kubernetes-route-10-200-2-0-24
51 |
52 | gcloud -q compute networks subnets delete kubernetes
53 |
54 | gcloud -q compute networks delete kubernetes-the-hard-way
55 | }
56 | ```
57 |
58 | compute address用に確保した`kubernetes-the-hard-way`を削除します:
59 |
60 | ```
61 | gcloud -q compute addresses delete kubernetes-the-hard-way \
62 | --region $(gcloud config get-value compute/region)
63 | ```
--------------------------------------------------------------------------------
/docs/images/tmux-screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/inductor/kubernetes-the-hard-way/74dfa54ba52cad888b4a64958f1a6d541f8bd35c/docs/images/tmux-screenshot.png
--------------------------------------------------------------------------------