从本地环境开始探索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编写的配置描述。