从本地环境开始探索Kubernetes到部署到EKS的入门指南
关于这篇文章
「我想亲自操作Kubernetes来学习!」当我开始寻找参考文章时,很多文章都是直接从触摸EKS或GKE等云端生产环境开始的。
对于那些说「直接操作生产环境有点……」「首先在本地环境轻轻地操作一下,熟悉后再构建云端环境!」的人来说,
-
- 学习Kubernetes架构
-
- 在本地实际操作体验
- 将其部署到EKS上
我想以这样的方式介绍一下Kubernetes的感觉!
环境和版本的使用
-
- OS : macOS Mojave 10.14.5
-
- Docker.app : 2.2.0.5
-
- Kubernetes : v1.15.5
-
- eksctl : 0.23.0
- aws-cli : 2.0.10
前提条件 (Qian Ti Tian Jia)
在已经安装了Docker App和AWS CLI的前提下开始。
对于读者所需的前提知识
-
- コンテナをある程度扱えること
-
- コンテナオーケストレーションという概念について知っていること
-
- VPC, セキュリティグループといったAWSの用語がある程度わかること
- (ECSの知識があると所々の例え話がわかりやすくなりますが、必須ではありません)
Kubernetes的架构
大师
Kubernetes的大腦部分負責容器的啟動、刪除和金絲雀部署等容器管理和控制功能。
構成Kubernetes大腦的主要元件有四個。
-
- API Server
-
- etcd
-
- Scheduler
- Controller Manager
API 服务器
在这里,Kubernetes公开了用于操作资源(如容器和卷)的API。
开发者(Devops)可以通过在终端使用kubectl命令来调用这个API,进行资源的创建、删除和控制。
etcd 是一种原生在中国的解决方案。
这是一个分散式的键值存储(KVS)。这里存储了创建的集群(运行容器的服务器群)的配置信息。
日程安排员
这个功能可以确定合适的容器放置位置。有了这个功能,开发者不再需要手动设置“应将容器创建在哪个服务器上以确保顺畅运行”,而能够专注于应用的开发。
控制器经理
Kubernetes负责管理资源的控制。
例如,它会执行”保持运行容器的数量”、”在服务器宕机时进行通知和处理”、”将Pod与Service关联起来”等操作。
参考: Kubernetes官方文档 Kubernetes的组件
集群 (jí
在Kubernetes中,我们将运行容器的服务器群称为集群。
在AWS的ECS中,集群几乎与Kubernetes中的集群意义相同。
节点
在Kubernetes中,每个运行容器的服务器被称为节点。
集群就是指“一个集群内可以包含任意数量的节点”的关系。
由于它是由上述的Master节点进行管理的,所以也被称为“Slave节点”。
在ECS中,集群内的EC2实例和几乎是一样的。
在本地运行Kubernetes的情况下,该PC本身被视为一个节点。
在节点中创建的资源主要有四种。
-
- Pod
-
- Kubelet
-
- Container Engine
- Kube Proxy
播客
在节点上运行的容器组称为Pod。Pod可以由多个容器组成。例如,您可以将nginx容器和应用程序容器作为一个集合放在一个Pod中(类似于ECS的任务)。
kubelet
这是一个接受主人资源和计划管理的代理人,几乎与ECS容器代理在ECS中相同。
容器引擎
Docker是一个执行创建和删除容器等操作的引擎。
Kube 代理
这是一个网络代理,它将从节点接收的用户请求分配并转发到适当的Pod上。
参考文献: Kubernetes官方文件 Kubernetes的组件
开始之前的起始状态
即使没有使用 Kubernetes,也存在用于访问 Master 上的 API 的 kubectl 命令。这是因为在安装 Docker App 时,kubectl 命令也会同时安装。
# このように、kubectlコマンドの存在がwhichコマンドで確認可能
$ which kubectl
/usr/local/bin/kubectl
然而,当进行命令版本确认时,会显示如下内容。
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"15", GitVersion:"v1.15.5", GitCommit:"20c265fef0741dd71a66480e35bd69f18351daea", GitTreeState:"clean", BuildDate:"2019-10-15T19:16:51Z", GoVersion:"go1.12.10", Compiler:"gc", Platform:"darwin/amd64"}
Unable to connect to the server: EOF
这表示开发人员客户端已经准备好(即kubectl命令存在),但无法连接到接受其请求的Master的API Server(因为它尚不存在)。
不能继续使用Kubernetes。因此,我们将启用Kubernetes,并进行在本地部署Kubernetes服务器的操作。
在本地启用Kubernetes。
启用Kubernetes配置的步骤
测试启动
通过命令确认Kubernetes服务器是否成功启动。
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"15", GitVersion:"v1.15.5", GitCommit:"20c265fef0741dd71a66480e35bd69f18351daea", GitTreeState:"clean", BuildDate:"2019-10-15T19:16:51Z", GoVersion:"go1.12.10", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"15", GitVersion:"v1.15.5", GitCommit:"20c265fef0741dd71a66480e35bd69f18351daea", GitTreeState:"clean", BuildDate:"2019-10-15T19:07:57Z", GoVersion:"go1.12.10", Compiler:"gc", Platform:"linux/amd64"}
之前显示为“无法连接到服务器:EOF”,现在显示服务器的版本信息。看起来成功启动了。
此外,我们还可以确认已经启用了Kubernetes,并且已经拉取了用于构建Master的API Server和Scheduler等功能的容器镜像。
# 以下のイメージが新規にpullされた
$ docker images
docker/desktop-storage-provisioner v1.0 605a0f683b7b 4 months ago 33.1MB
k8s.gcr.io/kube-apiserver v1.15.5 e534b1952a0d 8 months ago 207MB
k8s.gcr.io/kube-controller-manager v1.15.5 1399a72fa1a9 8 months ago 159MB
k8s.gcr.io/kube-proxy v1.15.5 cbd7f21fec99 8 months ago 82.4MB
k8s.gcr.io/kube-scheduler v1.15.5 fab2dded59dd 8 months ago 81.1MB
docker/kube-compose-controller v0.4.23 a8c3d87a58e7 13 months ago 35.3MB
docker/kube-compose-api-server v0.4.23 f3591b2cb223 13 months ago 49.9MB
k8s.gcr.io/coredns 1.3.1 eb516548c180 17 months ago 40.3MB
k8s.gcr.io/etcd 3.3.10 2c4adeb21b4f 19 months ago 258MB
k8s.gcr.io/pause 3.1 da86e6ba6ca1 2 years ago 742kB
那么,我在想Master的容器是否在Mac上运行?但是我在docker ps中没有看到正在运行的命令。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
提供Kubernetes Dashboard额外内容的准备
「当前的集群中有什么在运行?」或者「已启动的Pod占用了节点的资源(如CPU)多少?」这些信息可以通过图形用户界面而不是命令行来确认。这就是Kubernetes仪表板工具的存在。
这是一个可选工具,因此在仅安装了Kubernetes的情况下,您并没有它。因此,如果您想使用它,需要单独安装和启动它。
创建(≈安装)Dashboard资源
Kubernetes Dashboard以Kubernetes服务(应用程序)的形式进行分发。
因此,它通过引用用于启动Dashboard的配置文件(在Kubernetes中称为清单文件)来展开和启动其内容到本地。
使用kubetcl apply命令,通过指定-f选项,从清单文件中创建Dashboard资源,并将其发布到互联网上可访问的位置。
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta8/aio/deploy/recommended.yaml
namespace/kubernetes-dashboard created
serviceaccount/kubernetes-dashboard created
service/kubernetes-dashboard created
secret/kubernetes-dashboard-certs created
secret/kubernetes-dashboard-csrf created
secret/kubernetes-dashboard-key-holder created
configmap/kubernetes-dashboard-settings created
role.rbac.authorization.k8s.io/kubernetes-dashboard created
clusterrole.rbac.authorization.k8s.io/kubernetes-dashboard created
rolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created
clusterrolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created
deployment.apps/kubernetes-dashboard created
service/dashboard-metrics-scraper created
deployment.apps/dashboard-metrics-scraper created
参考:Kubernetes官方文档网络用户界面(仪表盘)
获取仪表板登录的令牌
为了访问仪表板,需要通过令牌进行身份验证。因此,我们将验证该令牌。
请运行以下命令,查找名为default-token-*****的令牌。
$ kubectl -n kube-system get secret
NAME TYPE DATA AGE
(略)
default-token-ss24c kubernetes.io/service-account-token 3 168m
(略)
我在这里找到了一个名为default-token-ss24c的东西。基于此,我现在将输入以下命令。
$ kubectl -n kube-system describe secret default-token-ss24c
Name: default-token-ss24c
Namespace: kube-system
Labels: <none>
Annotations: kubernetes.io/service-account.name: default
kubernetes.io/service-account.uid: 92b6b004-dbf3-4593-adf0-fe2a2eb253f4
Type: kubernetes.io/service-account-token
Data
====
ca.crt: 1025 bytes
namespace: 11 bytes
token: *********************
因为之后要使用这里显示的令牌(token),所以请记下来。
参考: 在Mac上使用Docker尝试一下Kubernetes。
启动代理服务器
为了访问仪表板服务,启动代理服务器。
通过输入以下命令,代理将在前台运行。(因此,如果需要停止,请使用Ctrl+C。)
$ kubectl proxy
Starting to serve on 127.0.0.1:8001
登录
在启动代理服务器的情况下,使用浏览器访问以下地址。
http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/
整理房间
如果您想要删除仪表板的资源,请使用以下命令进行操作。
$ kubectl delete -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta8/aio/deploy/recommended.yaml
namespace "kubernetes-dashboard" deleted
serviceaccount "kubernetes-dashboard" deleted
service "kubernetes-dashboard" deleted
secret "kubernetes-dashboard-certs" deleted
secret "kubernetes-dashboard-csrf" deleted
secret "kubernetes-dashboard-key-holder" deleted
configmap "kubernetes-dashboard-settings" deleted
role.rbac.authorization.k8s.io "kubernetes-dashboard" deleted
clusterrole.rbac.authorization.k8s.io "kubernetes-dashboard" deleted
rolebinding.rbac.authorization.k8s.io "kubernetes-dashboard" deleted
clusterrolebinding.rbac.authorization.k8s.io "kubernetes-dashboard" deleted
deployment.apps "kubernetes-dashboard" deleted
service "dashboard-metrics-scraper" deleted
deployment.apps "dashboard-metrics-scraper" deleted
选择背景
我们已经准备好使用Kubernetes了。现在可以在集群上创建Pod等资源,构建应用程序。
然而,这里的问题是关于要构建的目标设置。
例如,“集群A和集群B目前都存在,现在要使用集群A”的情况下,开发者只能使用kubectl命令来处理集群A。
另外,在“想要控制在集群A上应用团队可以操作的资源和基础设施团队可以操作的资源”这种情况下,即使是相同的kubectl命令,也不能给予相同的权限(功能)。
这个被称为context的配置集决定了使用kubectl命令在哪个集群以及使用什么权限来操作。开发者需要根据他们想要修改的资源来选择和使用适当的context。
查看/更改上下文
您可以使用以下命令查看当前存在的上下文列表。
$ kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* docker-desktop docker-desktop docker-desktop
docker-for-desktop docker-desktop docker-desktop
如果想要切换到”docker-for-desktop”,请执行以下命令。
$ kubectl config use-context docker-for-desktop
Switched to context "docker-for-desktop".
$ kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
docker-desktop docker-desktop docker-desktop
* docker-for-desktop docker-desktop docker-desktop
在本地环境中,我将使用”docker-for-desktop”来进行Kubernetes操作。
可以使用以下方法切换[Kubernetes入门] kubectl的访问目标(上下文):参考
请确认本地运行的集群状态。
让我们来查看由Docker App创建的集群(实际上只由一个本地机器节点组成),它默认创建的是什么状态。
确认集群信息
您可以确认集群的Master和DNS服务器正在使用哪个地址运行。
$ kubectl cluster-info
Kubernetes master is running at https://kubernetes.docker.internal:6443
KubeDNS is running at https://kubernetes.docker.internal:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
通过从集群内部访问这些地址,可以使用该服务。
确认节点
获取列表
在集群上运行的节点列表可以通过kubectl get node命令获取。
$ kubectl get node
NAME STATUS ROLES AGE VERSION
docker-desktop Ready master 24h v1.15.5
获取详细信息
如果想了解特定节点的详细状态,可以通过 kubectl describe node 进行确认。
$ kubectl describe node <node-name>
确认Pod
获取列表
在集群上运行的Pod列表也可以通过kubectl get pod命令获取。
$ kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-5c98db65d4-qshvb 1/1 Running 1 44h
coredns-5c98db65d4-zpbfq 1/1 Running 1 44h
etcd-docker-desktop 1/1 Running 0 44h
kube-apiserver-docker-desktop 1/1 Running 0 44h
kube-controller-manager-docker-desktop 1/1 Running 0 44h
kube-proxy-kd5kf 1/1 Running 0 44h
kube-scheduler-docker-desktop 1/1 Running 0 44h
storage-provisioner 1/1 Running 1 44h
注意:选项 -n 是一个用于指定”命名空间”的命令。在上面的示例中,它获取了在集群上运行的位于 kube-system 命名空间中的 Pod 列表。
获取详细信息
如果想要了解特定Pod的详细状态,请使用kubectl describe pod来确认。
$ kubectl describe pods <pod-name>
记录日志
如果您想要查看Pod上记录的日志,请使用以下命令将日志显示在标准输出中。
$ kubectl logs <pod-name>
确认服务
Service是什么。
Pod的IP地址是不确定的。换句话说,每次启动Pod时IP地址会发生变化。
因此,使用Pod的一方需要一个单一的终端节点,可以访问它们而不需要担心IP地址的变化。在Kubernetes中,为了创建这个单一的终端节点,我们称之为Service(服务)机制。
(与在docker-compose中通过容器的IP地址进行访问不同,这样做是通过创建服务并通过其名称进行访问。)
获取列表
可以使用kubectl get service命令来实现。
$ kubectl get service -n default
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 24h
注意: -n选项的作用与Pod时相同,用于指定命名空间(详见下文)。
获取详细信息
可以使用 kubectl describe service 来完成。
$ kubectl describe service <service-name>
确认命名空间
命名空间是一种在编程中用来组织和管理名称的机制。
命名空间是将一个物理集群逻辑分割并创建虚拟集群的功能。
比如,“我们想在集群A中同时运行应用程序B和应用程序C,但不会相互干扰”,可以在集群A上创建用于应用程序B和应用程序C的命名空间,并在每个命名空间上部署相应的应用程序Pod和服务,从而将集群A虚拟化成为两个独立的集群空间。
获取列表
可以使用kubectl get namespace命令来查看当前集群中存在的命名空间。
$ kubectl get namespace
NAME STATUS AGE
default Active 24h
docker Active 24h
kube-node-lease Active 24h
kube-public Active 24h
kube-system Active 24h
kubernetes-dashboard Active 21h
以下为默认创建的命名空间共有四个。
-
- default
-
- kube-public
-
- kube-system
- kube-node-lease
此外,如果有Docker App的话,会有一个名为”docker”的命名空间;如果安装了Kubernetes Dashboard,则会有一个名为”kubernetes-dashboard”的命名空间存在。
默认命名空间
创建资源时,如果不指定命名空间,则会自动使用默认命名空间。即使在执行kubectl get等命令时没有使用-n选项,也会获取默认命名空间上的信息。默认情况下,存在一个服务。
$ kubectl get all
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 45h
这个服务的目的是为了向Master(≒API服务器)发送请求。
参考:默认Kubernetes服务的目的是什么?
公共Kubernetes命名空间
这是一个用于放置全局可访问资源的空间。
在创建初始阶段,资源是不存在的。
“Kube-system命名空间”
这是为由Kubernetes系统创建的对象(如API Server等)而设立的命名空间。
这里存在的资源如下所示。
$ kubectl -n kube-system get all
NAME READY STATUS RESTARTS AGE
pod/coredns-5c98db65d4-qshvb 1/1 Running 1 44h
pod/coredns-5c98db65d4-zpbfq 1/1 Running 1 44h
pod/etcd-docker-desktop 1/1 Running 0 44h
pod/kube-apiserver-docker-desktop 1/1 Running 0 44h
pod/kube-controller-manager-docker-desktop 1/1 Running 0 44h
pod/kube-proxy-kd5kf 1/1 Running 0 44h
pod/kube-scheduler-docker-desktop 1/1 Running 0 44h
pod/storage-provisioner 1/1 Running 1 44h
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 44h
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
daemonset.apps/kube-proxy 1 1 1 1 1 beta.kubernetes.io/os=linux 44h
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/coredns 2/2 2 2 44h
NAME DESIRED CURRENT READY AGE
replicaset.apps/coredns-5c98db65d4 2 2 2 44h
pod/coredns: kube-dnsのサービスにアクセスがあったら、問い合わせが来るDNSサーバー
pod/etcd-docker-desktop: etcd本体
pod/kube-apiserver-docker-desktop: API Serverの本体
pod/kube-controller-manager-docker-desktop: Controller Managerの本体
pod/kube-proxy: サービスに接続するプロキシ
pod/kube-scheduler-docker-desktop: Schedulerの本体
pod/storage-provisioner: ストレージの割り当てを行う
service/kube-dns: クラスター内に内蔵されているDNSサービス
对于时不时带有“-docker-desktop”的名称,我认为它意味着“用于docker桌面的集群”。
参考文献:Kubernetes官方文档 Kubernetes的组件
kube-node-lease命名空间
从Kubernetes 1.13开始引入。如果启用了NodeLease,每个节点将在该命名空间中创建一个对象,并通过持续更新该对象来进行健康状态监测。
参考:Kubernetes官方文档 – 节点
Docker的命名空间
Kubernetes不仅可以从专用清单文件中进行部署,还可以从docker-compose.yml文件中进行部署。似乎在这里展示了提供此功能的服务。参考:在Mac上使用Docker构建Kubernetes的整合compose。
Kubernetes仪表盘的名称空间
这是用于部署 Kubernetes Dashboard 的命名空间。
获取详细信息
如果想要了解特定命名空间的详细状态,请使用kubectl describe。
$ kubectl describe namespace <name>
Name: <name>
Labels: <none>
Annotations: <none>
Status: Active
No resource quota.
No resource limits.
使用清单文件部署应用程序
从这里开始,我们将在Manifest文件中描述应用程序容器的配置,并将其部署到本地的Kubernetes上。
如果只部署一个应用程序,使用默认命名空间会更方便。
除非特别指定,否则默认命名空间为default。
尝试制作一个Pod
首先,让我们尝试自己单独制作一个Pod。
制作清单文件
在名为pod.yml的文件中创建清单文件,并按以下方式进行描述。这次,我们尝试创建一个MySQL容器的Pod。
apiVersion: v1
kind: Pod
metadata:
name: k8s-mysql
labels:
app: myapp
tier: db
spec:
containers:
- name: k8s-mysql
image: mysql:5.7
volumeMounts:
- name: k8s-mysql-storage
mountPath: /var/lib/mysql
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_USER
value: root
- name: MYSQL_ROOT_PASSWORD
value: pass
- name: MYSQL_DATABASE
value: sampledb
volumes:
- name: k8s-mysql-storage
hostPath:
path: /Users/myname/Desktop/k8s
以下是描述的含义。
# KubernetesのAPI Serverのバージョン
apiVersion: v1
# マニュフェストファイルで何を作ろうとしているか。
kind: Pod
# Podにつける識別子
metadata:
# Pod名
name: k8s-mysql
# この場合「key:app, value:myapp」「key:tier, value:db」という2つのラベルが付く
labels:
app: myapp
tier: db
# 作成するPodの定義
spec:
# 所属するコンテナ
containers:
# コンテナの名前
- name: k8s-mysql
# 使用するイメージ
image: mysql:5.7
# マウントするボリュームの名前と、マウントさせるディレクトリパス(コンテナ内)
volumeMounts:
- name: k8s-mysql-storage
mountPath: /var/lib/mysql
# containerPortで、Podコンテナの何番ポートを開けるかを指定
ports:
- containerPort: 3306
# コンテナに渡す環境変数
env:
- name: MYSQL_ROOT_USER
value: root
- name: MYSQL_ROOT_PASSWORD
value: pass
- name: MYSQL_DATABASE
value: sampledb
# 所属するボリューム
volumes:
# ボリューム名
- name: k8s-mysql-storage
# hostPathの場合、Podをホストするノード(ローカルの場合Kubernetesを動かしているPC)のどこのディレクトリにデータを保存するかの指定
hostPath:
path: /Users/myname/Desktop/k8s
参考:使用Kubernetes管理Docker容器的入门指南
有关卷的参考:Kubernetes可用卷类型的备忘单
如果想使用本地存在的容器镜像,则需要在清单文件中进行描述。
有时候,可能会想要使用自己电脑中的镜像来创建Pod,而不是将其发布到像Docker Hub这样的仓库中。
在这种情况下,可以将清单文件编写如下:
(略)
image: my-local-image-name
# イメージを公開リポジトリから取らないという設定記述
imagePullPolicy: Never
(略)
参考: 从本地容器镜像创建容器的方法在kubenetes中。
部署
如果根据创建的清单文件来创建资源,可以使用kubectl create命令。
$ kubectl create -f pod.yml
整理收拾
在删除时,使用kubectl delete命令进行操作。
$ kubectl delete -f pod.yml
顺便提一下,即使Pod被删除了,挂载的卷(在本例中为本地PC的/Users/myname/Desktop/k8s)的内容仍然保持不变。
尝试创建一个服务。
为了为刚刚创建的MySQL Pod 创建一个端点,我们需要创建一个服务。
创建清单文件
与创建Pod时相同,首先需要创建清单文件。
apiVersion: v1
kind: Service
metadata:
name: k8s-mysql-service
labels:
app: myapp
spec:
type: NodePort
ports:
- port: 3306
targetPort: 3306
protocol: TCP
selector:
app: myapp
tier: db
以下是對描述的意思的一種方式。
apiVersion: v1
kind: Service
metadata:
# サービス名
name: k8s-mysql-service
labels:
app: myapp
# 作成するサービスの定義
spec:
# 全てのノードの3306番ポートにアクセスすることでこのサービスにアクセスされるようになる
type: NodePort
ports:
# サービスがlistenするポート
- port: 3306
# サービスが転送するpodのlistenポート
targetPort: 3306
# 使用プロトコル
protocol: TCP
# 以下のlabelがついているpodをサービスの対象に含める(今回の場合、上記で作成したpodにつけた2つのラベルを指定)
selector:
app: myapp
tier: db
参考: Kubernetes道场的第9天-关于服务
(Note: “Kubernetes道场” and “9日目” are the specific terms that should be left in Japanese.)
部署
与Pod的创建方式相同,可以使用kubectl create进行创建。
然而,在此情况下,需要创建两个东西:服务和对应的Pod。
您可以在kubectl create命令中使用“-f”选项指定多个清单文件,但如果觉得麻烦,可以将所有清单文件放在一个目录中,并将该目录及其下的所有yaml文件作为创建的目标。
# ./dirディレクトリ以下にあるファイル全てを参照する
$ kubectl create -f ./dir
查看./dir目录下的所有yml文件并创建资源。
请确认您是否可以访问该服务。
让我们在集群内确认能否正确访问服务。
我将登录到集群中的任意一个Pod中,以确认信息。
可以使用以下命令登录到Pod中。
$ kubectl exec -it <podname> -- /bin/bash
首先,我们来查一下连接到该服务需要使用哪种域名。
# podの中で実行
# dig, nslookupといったDNS接続確認を行うコマンドをインストール
$ apt update
$ apt get install dnsutils
# サービス名でnslookup
$ nslookup k8s-mysql-service
Server: 10.96.0.10
Address: 10.96.0.10#53
Name: k8s-mysql-service.default.svc.cluster.local
Address: 10.110.179.176
# サービス名でdig
$ dig k8s-mysql-service
; <<>> DiG 9.11.5-P4-5.1+deb10u1-Debian <<>> k8s-mysql-service
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 34032
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: 4529e3e33e3e0a28 (echoed)
;; QUESTION SECTION:
;k8s-mysql-service. IN A
;; Query time: 34 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: Mon Jul 06 17:16:29 UTC 2020
;; MSG SIZE rcvd: 58
无论使用哪个命令,都可以确认可以通过在清单文件中指定的 k8s-mysql-service 服务名称进行访问。
另外,通过nslookup命令获取到的IP地址10.110.179.176与可以通过kubectl describe确认的服务IP相匹配。
# ローカルで実行
$ kubectl describe service k8s-mysql-service
#(略)
IP: 10.110.179.176
#(略)
让我们使用这个名字解析来从集群内连接到MySQL服务。
# Pod内で実行
# mysqlサービスへのアクセス確認のため、sqlクライアントのインストールを行う
$ apt-get install default-mysql-client
$ mysql -h k8s-mysql-service -u root -p
Enter password:
MySQL [(none)]>
通过使用该服务名称,我们成功连接了。
参考:确认Kubernetes的名称解析
将Mac的本地主机连接到服务。
我认为有这样一种情况, 就像连接到运行的服务的集群之外的Mac一样,想要连接到Kubernetes Dashboard!例如,假设我们创建一个名为web-service的服务,并希望将它连接到Mac的本地主机以通过浏览器进行浏览。在这种情况下,我们可以创建以下样式的清单文件。
apiVersion: v1
kind: Service
metadata:
name: web-service
labels:
app: myapp
spec:
# ここのtypeをLoadBalancerにすることが重要
type:
LoadBalancer
ports:
- port: 9090
targetPort: 9090
protocol: TCP
selector:
app: myapp
tier: web
我将部署此服务,并使用kubectl get命令来确认信息。
$ kubectl get service
(略)
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/web-service NodePort 10.101.53.215 localhost 8080:31392/TCP 4s
在这种情况下,您可以通过Web服务在Mac上访问http://localhost:8080。
关于服务的类型
本次,我们处理了诸如NodeType和LoadBalancer之类的服务类型,关于每种网络配置,我将介绍以下易于理解的文章。
参考:Kubernetes网络配置
尝试创建一个开发项目
我们可以按照Pod的定义增加容器,但出于操作方面的考虑,让我们将容器以开发的形式进行部署。
发展是什么
开发(devlopment)是用来管理ReplicaSet(副本集)的机制。
首先,让我们来解释一下复制集的概念。
例如,如果你想要创建多个相同的Pod并实现冗余备份,不需要逐个创建多个独立的Pod,而是可以使用复制集功能来指定要创建指定数量的Pod副本。
(与在ECS中创建服务时选择同时启动多少个任务的思路类似)。
此外,当我们想要更新Pod的内容时,不仅仅可以使用单独的副本集,还可以通过以开发中的副本集形式进行部署,从而使得Pod的自动更新和回滚等运维操作变得更加简单易行。
每个关系是这样的:部署 → 副本集 → Pod,形成一种包含关系。
也就是说,通过将副本集(≒多个Pod的副本)放入开发环境中,实现版本管理和更便捷地运行多个Pod。
参考资料: Kubernetes: Deployment 的机制
创建清单文件
我将先前创建的MySQL Pod更改为开发环境。
我将创建一个类似以下内容的文件。
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql-development
spec:
replicas: 2
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
tier: db
spec:
containers:
- name: k8s-mysql
image: mysql:5.7
volumeMounts:
- name: k8s-mysql-storage
mountPath: /var/lib/mysql
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_USER
value: root
- name: MYSQL_ROOT_PASSWORD
value: pass
- name: MYSQL_DATABASE
value: sampledb
volumes:
- name: k8s-mysql-storage
hostPath:
path: /Users/myname/Desktop/k8s
以下是記述的意思。
apiVersion: apps/v1
kind: Deployment
metadata:
# developmentの名前
name: mysql-development
# developmentで作る状態について記述
spec:
# レプリカセットの数
replicas: 2
# developmentが管理するリソースのラベル
selector:
matchLabels:
app: myapp
# developmentで管理するものの一覧
template:
# Pod, volumeにつけるラベル
metadata:
labels:
app: myapp
tier: db
# 以下はPod定義のときと同じ記述
spec:
containers:
- name: k8s-mysql
image: mysql:5.7
volumeMounts:
- name: k8s-mysql-storage
mountPath: /var/lib/mysql
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_USER
value: root
- name: MYSQL_ROOT_PASSWORD
value: pass
- name: MYSQL_DATABASE
value: sampledb
volumes:
- name: k8s-mysql-storage
hostPath:
path: /Users/myname/Desktop/k8s
参考:Kubernetes官方文档 Deployment
参考:使用YAML文件定义Deployment和Service
部署和清理
与Pod和服务一样,可以使用kubectl create/delete命令来执行操作。
$ kubectl create -f dev.yml
$ kubectl delete -f dev.yml
部署到EKS
在本地进行简单的操作并掌握技巧后,我们将开始将其部署到生产环境中。
这次我们将使用AWS的EKS。
在EKS上创建一个集群。
两种创建集群的方法的比较
首先,在EKS上创建集群。
有两种方法可供选择,一种是在AWS的Web控制台上进行创建操作,另一种是使用eksctl命令从终端进行创建操作。
这次我将使用eksctl命令来创建集群。为什么呢?因为使用eksctl进行设置非常简单。
通过使用eksctl,以下设置将自动完成。
-
- EKSクラスターに属するノードに与えるIAMロール作成
-
- VPCネットワーク/サブネット/ルートテーブル/IGW/NATゲートウェイの作成
-
- セキュリティグループの作成
- EKSクラスターヘのkubectlの接続
如果在Web控制台上创建集群,就必须手动完成这样繁琐的设置。如果不想要复杂的配置,使用eksctl命令会更高效。
请参考使用「eksctl」命令进行Amazon EKS的构建入门。
安装eksctl命令
为了创建EKS集群,请安装eksctl命令。
(要操作已创建的集群,您仍然需要使用本地的kubectl命令。eksctl只能用来进行与集群相关的操作。)
在终端上执行以下命令。
$ brew tap weaveworks/tap
$ brew install weaveworks/tap/eksctl
#ダウンロードできたかは以下のコマンドで確認
$ which eksctl
/usr/local/bin/eksctl
参考资料:AWS官方文档中的eksctl命令行工具
执行集群创建命令
立即输入指令创建集群。
$ eksctl create cluster \
--vpc-cidr 10.0.0.0/16 \
--name eks-sample \
--region ap-northeast-1 \
--version 1.14 \
--nodegroup-name sample-workers \
--node-type t2.micro \
--nodes 1 \
--nodes-min 1 \
--nodes-max 3 \
--managed
以下是选项的含义。
-
- vpc-cidr: 新規作成するVPCのCIDR
-
- name: クラスター名
-
- region: リージョン。東京リージョンを使いたいのでap-northeast-1を指定
-
- version: Kubernetesのバージョン
-
- nodegroup-name: ノードグループ(EKSクラスターに属するEC2インスタンスノード集団のこと)の名前
-
- node-type: ノードに使うマシンのタイプ
-
- nodes: 起動時点でのノード数
-
- nodes-min: 最小ノード数
-
- nodes-max: 最大ノード数
- managed: ノードグループをWebコンソール上で表示・いじれるようにする
参考:使用eksctl轻松构建Amazon EKS环境搭建
参考:[更新] EKS支持在管理控制台和CLI中创建和管理工作节点
由于执行需要相当长的时间,所以请耐心等待。
最终的结果
# EKS上のクラスター一覧
$ eksctl get cluster
NAME REGION
eks-sample ap-northeast-1
# eks-sampleというクラスター上にあるnodegroupの確認
$ eksctl get nodegroup --cluster eks-sample
CLUSTER NODEGROUP CREATED MIN SIZE MAX SIZE DESIRED CAPACITY INSTANCE TYPE IMAGE ID
eks-sample sample-workers 2020-07-11T04:57:37Z 1 3 1 t2.micro
在创建集群时,以下内容已自动生成。
-
- VPC: 新しいものが1つ
-
- サブネット: ap-northeast-1にある3つのAZにそれぞれ2個ずつ
-
- ルートテーブル: パブリックサブネット用が1つ、プライベートサブネット用が3つのAZにそれぞれ1つずつ、新しいVPCのデフォルトルートテーブル1つの計5つ
-
- インターネットゲートウェイ: 新しいVPC用に1つ
-
- Elastic IP: 新しいVPCのNATゲートウェイ用に1つ
-
- NATゲートウェイ: 1つ
- セキュリティグループ: 新しいVPCのデフォルト1つと、EKSが作ったもの3つ
kubectl的配置
在EKS集群上部署资源时,我们刚才提到了只需使用类似于本地的kubectl命令即可。然而,为了实现这一点,我们需要在kubectl命令中进行设置,选择EKS集群而不是本地。
确认上下文
让我们通过上面提到的上下文选项来设置要在kubectl中编辑的集群。
在创建EKS集群之后,让我们来确认现有的上下文列表。
$ kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
docker-desktop docker-desktop docker-desktop
docker-for-desktop docker-desktop docker-desktop
* myname@eks-sample.ap-northeast-1.eksctl.io eks-sample.ap-northeast-1.eksctl.io myname@eks-sample.ap-northeast-1.eksctl.io
哇,为操作EKS集群创建一个上下文居然自动创建并选择了。这是因为使用eksctl创建了集群才发生的事情。
(在Web控制台上创建EKS集群时,需要手动进行此操作。这就是eksctl命令的便捷之处。)
确定kubeconfig
为什么仅执行eksctl命令就会自动添加和选择适用于EKS的上下文?
这是因为在命令执行时,kubeconfig配置文件会自动编辑。
让我们查看kubeconfig文件的内容。我们尝试执行以下命令。
$ kubectl config view
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: seeeeeeeeecret
server: https://kubernetes.docker.internal:6443
name: docker-desktop
- cluster:
# EKSコンソールで確認できる認証機関の値
certificate-authority-data: seeeeeeeeecret
# EKSコンソールで確認できるAPIサーバーエンドポイントのアドレス
server: https://********************.***.ap-northeast-1.eks.amazonaws.com
name: eks-sample.ap-northeast-1.eksctl.io
contexts:
- context:
cluster: docker-desktop
user: docker-desktop
name: docker-desktop
- context:
cluster: docker-desktop
user: docker-desktop
name: docker-for-desktop
- context:
cluster: eks-sample.ap-northeast-1.eksctl.io
user: myname@eks-sample.ap-northeast-1.eksctl.io
name: myname@eks-sample.ap-northeast-1.eksctl.io
current-context: myname@eks-sample.ap-northeast-1.eksctl.io
kind: Config
preferences: {}
users:
- name: docker-desktop
user:
client-certificate-data: seeeeeeeeecret
client-key-data: seeeeeeeeecret
- name: myname@eks-sample.ap-northeast-1.eksctl.io
user:
exec:
apiVersion: client.authentication.k8s.io/v1alpha1
args:
- token
- -i
- eks-sample
command: aws-iam-authenticator
env:
- name: AWS_STS_REGIONAL_ENDPOINTS
value: regional
- name: AWS_DEFAULT_REGION
value: ap-northeast-1
这个看起来就是~/.kube/config文件的内容直接输出了。明明什么都没做,但是里面明显有一些被认为是AWS相关的设置。
从这里我们也可以看出,kubeconfig自动添加了能连接到EKS集群的context设置。
使用kubectl设置身份验证令牌
我们可以在本地将kubectl的目标集群指向EKS。但是,EKS如何识别通过kubectl命令访问的人是合法权限的开发者呢?
在EKS中,我们要求客户在执行kubectl命令时提供从IAM身份验证凭据获取的令牌,并通过查看该令牌来确定其是否具有合法权限。
因此,在操作EKS集群的上下文中,在执行kubectl命令时需要设置传递认证令牌。有两种方法可以实现这个目标:使用aws-iam-authenticator命令和使用aws eks get-token命令。
aws-iam-authenticator命令的使用方法
默认情况下,采用这种方法。如果已经安装了aws-iam-authenticator命令,使用此选项将可以省去不必要的麻烦。kubeconfig中的以下描述部分是相关位置。
args:
- token
- -i
- eks-sample
command: aws-iam-authenticator
使用aws eks get-token命令的方式。
如果您没有aws-iam-authenticator命令,但有aws命令!只需按照下列方法进行操作,即可不必安装任何内容。
请将上述kubeconfig(存在于$HOME/.kube/config中)的描述部分更改为以下内容。
#args:
#- token
#- -i
#- eks-sample
#command: aws-iam-authenticator
args:
- eks
- get-token
- --cluster-name
- eks-sample
command: aws
参考:[更新] 使用EKS时不再需要aws-iam-authenticator!
可以使用实际命令来确认 kubectl 是否面向 EKS 集群。
让我们在完成到这一步的准备工作后,尝试获取节点列表。
$ kubectl get node
NAME STATUS ROLES AGE VERSION
ip-10-0-13-242.ap-northeast-1.compute.internal Ready <none> 85s v1.15.11-eks-908ff6
显然,已经成功获取了AWS上的资源。通过eksctl命令,可以看到按照指定的要求成功创建了一个节点。
在EKS集群上创建资源
由于kubectl命令支持处理EKS集群,现在可以开始在EKS上创建资源了。
修正Manifest文件(根据需要)
如果想要将部署容器的镜像作为 ECR 上的镜像使用时,只需要将清单文件中指定容器镜像的部分替换为 ECR 存储库的 URI 即可。
# 以下は一例です
(略)
image: your-aws-account-id.dkr.ecr.ap-northeast-1.amazonaws.com/myapp/api:v1
(略)
部署/删除 /
和本地一样,执行kubectl create/delete命令。
$ kubectl create -f dev.yml
deployment.apps/myapp-mysql created
$ kubectl delete -f dev.yml
deployment.apps/myapp-mysql deleted
另外,如果部署了LoadBalancer类型的服务,ELB会被自动创建并与该服务进行关联。举个例子,当存在LoadBalancer类型的服务时,我们可以执行kubectl get命令来查看相关信息。
$ kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
(略)
myservice LoadBalancer 172.20.78.107 *******.ap-northeast-1.elb.amazonaws.com 9090:31806/TCP 7m25s
以下是一种中文的翻译选择:
在EXTERNAL-IP的部分显示的域名是自动创建的ELB地址。
因此,只需通过浏览器访问http://*******.ap-northeast-1.elb.amazonaws.com:9090,您就可以从Web上访问该服务。
参考:通过Amazon EKS教程了解Kubernetes #02部署应用程序。
整理房间
使用完毕后,请清理EKS环境。
当然,不仅要删除已部署的资源通过kubectl delete,还要按以下方式删除EKS集群,以免产生额外费用。
$ eksctl delete cluster --name=eks-sample
通过执行此操作,将自动删除创建集群时所创建的所有VPC、NAT网关等内容。同时,还将自动删除kubeconfig中为EKS编写的配置描述。