我为初学者创建了一个基于AWS的容器入门实践教程
由于我决定在职场上组织上述的学习会,所以我会留下参与者的步骤指南作为参考。
首先
这是针对这样的人的实践课程。
-
- コンテナって興味あるけど自分で触ったことないからイメージわかない
- Kubernetesに入門してみたい
以下是所需的项目。
-
- PC:Win/Mac両対応。会社の業務OA端末(制限付きWindows)でも問題なし。
- AWSアカウントとIAMユーザー:社内向けにはわたしの方で用意しました。
在浏览器中登录AWS并启动操作终端。
确认虚拟终端已经准备好,并且光标正在闪烁时,复制以下命令并粘贴到CloudShell中进行执行。
※ 环境准备是参考这篇文章。
# ディレクトリ作成
mkdir -p $HOME/.local/bin
cd $HOME/.local/bin
# kubectl のインストール
curl -LO "https://dl.k8s.io/release/$(curl -LS https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl
# eksctl のインストール
curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp
sudo mv /tmp/eksctl $HOME/.local/bin
# ホームディレクトリに戻る
cd $HOME
在CloudShell上,您可以通过这个来安装Kubernetes hands-on所需的工具。
然后,您可以在CloudShell上运行以下命令来创建EKS集群。
※ 这是一个简短的命令,所以尽量手动输入而不是复制粘贴,这样可以加深理解。
eksctl create cluster
这将需要大约20分钟才能完成。在背后,将会自动执行一个名为CloudFormation的IaC工具,并且将构建所需的基础设施,如VPC、EC2等,用于EKS集群。
一旦到达这个地步,我打算在等待时间内进行一场关于“容器是什么?”的纸片剧时光。
※ 如果在途中遇到困难,讲师会提供支持,请毫不犹豫地发言或在聊天栏里提问。
等待时间:纸片剧时间
“什么是容器?(Kubernetes入门)”
如果在进行这个过程中能够经过大约20分钟的时间,我认为EKS集群的创建将会完成。
如果在CloudShell中显示以下输出,并且提示符的光标闪烁并处于可操作状态,那就没问题了。
2022-01-30 00:19:08 [✔] EKS cluster "attractive-party-1643500815" in "ap-northeast-1" region is ready
请务必查看此处显示的您的EKS集群名称。似乎会随机设置各种古怪的英语动物名称等。
(由于在使用eksctl创建集群时未指定选项,因此集群名称和节点数量等都是自动设置的)
※ 当您在CloudShell上长时间没有操作时,会被自动断开连接。
但是,只需按下Enter键,几秒钟后即可立即恢复并继续进行终端操作。
然而,从AWS管理控制台的图形用户界面仅能查看到的范围仅限于此!在工作节点上实际运行的容器世界只能通过命令行来查看,因此需要返回到CloudShell。
终于要开始实践K8s了。
因为Cybozu先生的新人培训资料非常易懂且出色,所以我们这次将其作为参考文本。
尽管使用Minikube非常方便,但对于Windows系统来说有一些复杂,还需要管理员权限。因此,为了公司内部的研讨会,我在这次活动中进行了一些调整,利用AWS使得所有人都能够通过浏览器操作,使用公司受限的Windows电脑。(翻译仅供参考)
版权所有(C)2019 Cybozu
https://github.com/cybozu/introduction-to-kubernetes/blob/master/LICENSE
暂时先确认一下现状。
在K8s的世界中,我们使用”kubectl”命令来操作容器。首先,让我们尝试确认数据平面的工作节点有多少台。
※由于这是一个简短的命令,请手动输入而不是复制粘贴以加深理解。
kubectl get node
我想大概会输出如下结果。
就像刚才在管理控制台上看到的那样,EC2的名称显示了两个实例。
NAME STATUS ROLES AGE VERSION
ip-192-168-11-13.ap-northeast-1.compute.internal Ready <none> 3h6m v1.21.5-eks-9017834
ip-192-168-72-188.ap-northeast-1.compute.internal Ready <none> 3h6m v1.21.5-eks-9017834
此外,尽管Pod(容器)应该还没有创建任何内容,但为了确认,我们可以尝试进行列表显示。
kubectl get pod
2-2. 心跳加速!尝试部署第一个Pod
那么,现在我们来创建一个安装了我们喜欢的应用程序的Pod(容器)。
由于创建Pod相当复杂(需要指定名称、使用哪个容器镜像、以及需要哪些规格等等),我们将像在家庭餐厅一样,将订单写在点菜单上,然后将指示传达给控制平面。
订单书必须按照一个名为YAML的文本文件格式进行编写。
订单书被称为“清单”。
※ YAML可能会让人感到陌生,但实际上它只是一系列简单的文本条目,就算是猴子也能理解。
我最初想要尝试将代表性的Web服务器产品”NGINX”作为容器来运行。
首先,在记事本上复制以下文本,并保存在公司电脑桌面上,命名为”nginx-pod.yaml”。
apiVersion: v1
kind: Pod
metadata:
name: my-nginx
labels:
component: nginx
spec:
containers:
- name: nginx
image: nginx:latest
只需这样,订单就完成了。
由于NGINX是一款受欢迎的开源软件,因此已经有其他人创建并公开了容器镜像,所以在订单中指定重用它。
那么,我们将使用这张订单表来部署Pod。
命令如下所示。
kubectl apply -f nginx-pod.yaml
当Pod成功创建后,我们可以列出并确认一下。请再次执行之前输入的以下命令。
kubectl get pod
然后,如下所示,我订单出现了一个名为”my-nginx”的Pod。
如果状态为”Running”,那就意味着它已经启动并正在运行中。我们可以看到,它的启动速度远远快于虚拟机启动。
NAME READY STATUS RESTARTS AGE
my-nginx 1/1 Running 0 82s
附带提一下,查看Pod详细信息的命令如下。
kubectl describe pod my-nginx
当尝试运行时,我们可以看到各种输出,如Pod名称、IP地址、事件日志等。当Pod不正常时,可以通过这种方式来检查日志等信息。
2-3. 我们来尝试登录Pod吧。
为了让人们真正感受到Pod的存在,不仅仅看外表,让我们登录到Pod内部来体验一下。
使用kubectl exec命令,在Pod内部执行bash命令进行尝试。
kubectl exec -it my-nginx -- bash
由于我对在Pod中是否真的放置了某物有些怀疑,因此我想要在Pod内对自己使用curl命令进行测试。
简单来说,curl是一种功能,可以在命令行上模拟对任意URL的HTTP访问。
curl localhost
因为NGINX是一个Web服务器,所以它能够使其他人能够访问这样的页面。当我将curl的目的地指定为本地主机(我自己)时,我看到了这个页面,所以毫无疑问我登录到了NGINX Pod上是正确的。
当您满意后,先使用exit命令退出my-nginx Pod,然后返回CloudShell。
2-4. 尝试从一个Pod访问另一个Pod。
接下来,我们将尝试不仅从CloudShell中直接查看Pod,还会尝试从一个Pod访问另一个Pod。这主要是为了确认服务器间的通信是否正常。
首先,我们将同时部署一个独立的Linux Pod作为跳板,除了现有的NGINX Pod。
请将以下内容复制粘贴到“fumidai-pod.yaml”文件中,并保存到公司电脑的桌面上。然后,将该文件像之前一样上传到CloudShell中,进行尝试。
apiVersion: v1
kind: Pod
metadata:
name: fumidai
spec:
containers:
- name: bastion
image: debian:stable
command: ["sleep", "infinity"]
让我们使用kubectl把这个只安装了Debian Linux的简单Pod添加并部署一下。
kubectl apply -f fumidai-pod.yaml
如果我们成功部署,让我们来确认当前的Pod列表。你可能已经开始记住命令了吧?
NAME READY STATUS RESTARTS AGE
fumidai 1/1 Running 0 12s
my-nginx 1/1 Running 0 115m
然而要准确地说,不清楚哪个Pod放在哪个节点(EC2)上。
节点和Pod的管理交给了K8s这个可靠的世界,我们作为用户只需订单”需要什么样的Pod”就好。
好的,现在登录到跳板Pod上,我想在那里尝试访问NGINX Pod之前,需要确认一下目标NGINX Pod的IP地址。
通过使用”Pod一覧显示命令 -o wide”,您也可以知道IP地址。
kubectl get pod -o wide
你知道NGINX的IP地址吗?那么我们首先用kubectl exec登录到跳板Pod。
kubectl exec -it fumidai -- bash
当操作提示变为跳板Linux的root账户后,请尝试访问旁边的my-nginx Pod的HTTP。然而由于未安装curl命令,执行以下命令进行安装。
apt update
apt install -y curl
如果成功安装了curl,那么让我们尝试在之前确认的my-nginx Pod的IP地址上进行命令输入。
curl http://192.168.xx.xx
如果成功到这个地方,我们再用 “exit” 命令从跳板 Pod 中退出。
增加多个具有相同用途的Pod来实现冗余备份。
目前,我們只有一個my-nginx Pod,但如果它出現故障,那麼將無法訪問任何人「Welcome to nginx!」頁面。為了避免這種情況,我打算編寫一個訂單,要求始終運行三個這樣的Pod。
刚刚写的YAML是一个名为”Pod”的订单,但是如果要同时订购多个Pod的话,需要创建另一种名为”ReplicaSet”的订单。
这次我们将把它命名为”triple-nginx”的ReplicaSet。
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: triple-nginx
labels:
component: nginx
spec:
replicas: 3
selector:
matchLabels:
component: nginx
template:
metadata:
labels:
component: nginx
spec:
containers:
- name: nginx
image: nginx:latest
将这份文件保存在本地,并将其作为”nginx-replicaset.yaml”文件上传到CloudShell上去吧。在部署这份订单之前,先确认一下当前Pod的列表。
kubectl get pod
让我们使用上述副本集来部署Pod,其中包含一个最初通过Pod清单部署的my-nginx Pod和一个跳板服务器,总共有两台设备。
kubectl apply -f nginx-replicaset.yaml
在已经存在一个NGINX的Pod的地方,我提交了一个订单,希望可以运行3个NGINX。我们可以使用kubectl get pod命令来确认结果。
NAME READY STATUS RESTARTS AGE
fumidai 1/1 Running 0 48m
my-nginx 1/1 Running 0 164m
triple-nginx-gt89t 0/1 ContainerCreating 0 3s
triple-nginx-xfdqc 0/1 ContainerCreating 0 3s
然后,可以看到从名为”triple-nginx”的副本集生成的自动命名Pod正在准备启动的过程中,总共有两个。
为什么可以将现有的一个设备视为相同的用途呢?因为最先部署的“Pod”用的清单和现在的“Replicaset”用的清单,都在其中添加了标签“component: nginx”。
根据这个标签,Replicaset会监控Pod的运行数量的规格。
(前略)
metadata:
(中略)
labels:
component: nginx
(後略)
那么,让我们来恶作剧一下。
如果故意删除一个NGINX的Pod,会发生什么呢?
kubectl delete pod my-nginx
如果成功删除了Pod,则立即使用”kubectl get pod”命令确认Pod的列表。然后,您会发现惊人的是,从”triple-nginx”副本集立即生成了一个新的Pod。
NAME READY STATUS RESTARTS AGE
fumidai 1/1 Running 0 65m
triple-nginx-gt89t 1/1 Running 0 16m
triple-nginx-x2k5x 1/1 Running 0 4s
triple-nginx-xfdqc 1/1 Running 0 16m
所以,我认为我们可以亲身感受到在Pod发生故障时的自动修复速度非常快。
2-6. 对多个Pod进行负载均衡。
既然我们将3个用途相同的Pod实现了冗余备份,那么我们也应该修改访问Pod的方式,而不是通过指定IP地址访问,而是通过名称进行访问。
为此,我们需要创建一种名为”服务”的新型订单。这次我们将创建一个名为”my-nginx”的服务。
apiVersion: v1
kind: Service
metadata:
name: my-nginx
spec:
selector:
component: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
你是否注意到实际上在这里还设置了一个名为component: nginx的标签呢?让我们将这个”nginx-service.yaml”再次上传到CloudShell,并尝试部署它。
kubectl apply -f nginx-service.yaml
你可以使用kubectl来查看这个“服务”。
试试kubectl get service,你会发现除了默认的“kubernetes”服务外,刚才部署的“my-nginx”服务也在运行。
让我们尝试一下,不直接指定IP地址,而是使用curl访问“my-nginx”服务,从踏台Pod到达它。
kubectl exec -it fumidai -- bash
curl http://my-nginx
如果能够做到这一步,就从踏踏板上退出并离开吧。
尝试对多个Pod进行滚动更新。
最后我会尝试一些有点困难的操作。
目前,“triple-nginx”副本集中正在运行3个Pod,但由于开发团队更新了NGINX容器,希望将其替换为新的Pod。
然而,“Welcome to nginx!”是一个每天24小时都有访问的受欢迎网站,所以我们希望尽量不影响客户体验,希望逐个地偷偷更新每个Pod。
当时使用复制集进行滚动更新非常麻烦。原因是需要创建两个版本的复制集,并逐步增加新复制集中 Pod 的数量,同时逐步减少当前复制集中 Pod 的数量,这意味着需要多次执行 kubectl apply 的繁琐操作。
那么首先,为了简化问题,我们先暂时删除复杂的下位互换的”复制集”。
kubectl delete replicaset triple-nginx
我们可以为“部署”创建一个YAML清单文件。创建当前版本和新版本,并都上传到CloudShell。
这是指定了NGINX 1.20容器镜像的「nginx-deployment-v1.yaml」(当前版本)。
apiVersion: apps/v1
kind: Deployment
metadata:
name: triple-nginx
labels:
component: nginx
spec:
replicas: 3
selector:
matchLabels:
component: nginx
template:
metadata:
labels:
component: nginx
spec:
containers:
- name: nginx
image: nginx:1.20
「nginx-deployment-v2.yaml」(新版本)
这里指定了NGINX 1.21的容器镜像。
apiVersion: apps/v1
kind: Deployment
metadata:
name: triple-nginx
labels:
component: nginx
spec:
replicas: 3
selector:
matchLabels:
component: nginx
template:
metadata:
labels:
component: nginx
spec:
containers:
- name: nginx
image: nginx:1.21
如果能够将这两个文件上传到CloudShell上,首先使用当前版本的部署来部署Pod。
kubectl apply -f nginx-deployment-v1.yaml
当尝试运行“kubectl get pod”命令时,您会发现有3个NGINX的Pod正在运行。
在这种情况下,应用新版本的部署将进行滚动更新。
然而,由于普通方法无法清楚地了解进展,所以我希望在CloudShell的另一个选项卡中登录到跳板Pod上,并且将NGINX版本确认命令设置为每0.1秒连按一次,以便做好准备。
首先,从CloudShell屏幕右上角的“Action”按钮中选择“New tab”并点击。
在新打开的控制台中,执行以下命令,从跳板Pod进行确认命令操作。
kubectl exec -it fumidai -- bash
while true; do echo "-------"; date; curl -s -i my-nginx | grep -E 'Server'; sleep 0.1; done
让我们返回到CloudShell的第一个选项卡,并尝试应用新版本的部署。
kubectl apply -f nginx-deployment-v2.yaml
通常在商业环境中部署K8s的Pod时,通常使用”Deployment”而不是”Pod”或”ReplicaSet”,因此请记住这一点。严格来说,通过使用Deployment,K8s会自动管理底层对象,部署ReplicaSet,进而部署Pod。
通过这种方式,您现在已经掌握了如何在EKS环境中运行多台可以滚动更新的NGINX容器!
整理
为了节省不必要的花费,让我们删除创建的群集。
首先,请确认群集的名称…
kubectl config get-clusters
eksctl delete cluster \
--name 消したいクラスター名 \
--wait
若因错误而失去连接的人,导师会稍后清除,所以请放心地放置不管。
概述
在K8s的世界中,根据以下介绍的四种”注文書(マニフェスト)”的定义,它们分别被称为”资源”。
-
- Pod
-
- Replicaset
-
- Deployment
- Service
「资源」这个词可能不太容易理解,但在K8s世界中类似于“概念”。
这些“资源”实际上生成的东西被称为“对象”。
我也是一个刚开始学习Kubernetes的初学者,但是我觉得只要你亲自动手操作一下实体设备,对于容器的操作大概就能有点印象了吧。
对于Cybozu公司能够为外部人员提供这么明了易懂的新人培训资料,我真的非常感激!
在公司内的学习会上,我会统一删除本次分发的IAM用户和您创建的各种AWS资源,请放心。