Use k8s on AWS - EKS service
k8s最近是风头很盛,因为它解决了容器集群的管理和调度问题,所以大家都想一试究竟——包括我,一般如果没有云账号的同学,只能自己下载k8s的软件装在本地服务器上,还要下载k8s相关的插件,配置网络等等一系列设置,经过各种调试才能正常运行。这种方式对于用过云的朋友自然是拒绝的——包括我,实用主义告诉我们,只要更快达到目的不论过程和手段,能直接用托管的,干嘛费力费时找条弯路走呢。
-- D.C
先上个珍藏多年的k8s基础原理图:
名词解释
- Master : 包工头主节点,用来调度k8s集群,头上接收外部的api请求,从而进行任务分配和调度等。
kube-apiserver : k8s对外的服务入口,通信纽带,无状态,水平扩展。
Kube-scheduler : 负责对pod的任务调度。
kube-controller-manager : 处理node节点的当机啊,pod的副本数啊,管理endpoint终端节点,连接service和pod、为新的命名空间创建默认api token和accounts。
etcd : etcd是kubernetes集群用来存储集群相关数据的数据仓库。
- node : worknodes,干活的节点。执行包工头master节点指派的搬砖任务。
kubelet :负责启动停止容器,保证容器运行。
kube-proxy :负责根据service生成网络规则,生成路由规则。
Docker engine : 这个不用说了,一个pod里面可以有一个或多个容器。
- Pod : k8s 以pod为最小单位进行调度、扩展、共享资源、管理生命周期。在一个pod里所有的容器共享以下资源:
PID命名空间 : Pod中的不同应用程序可以看到其他应用程序的进程ID。
网络命名空间 : Pod中的多个容器能够访问同一个IP和端口范围。
IPC命名空间 : Pod中的多个容器能够使用SystemV IPC或POSIX消息队列进行通信。
UTS命名空间 : Pod中的多个容器共享一个主机名。
Volumes(共享存储卷) : Pod中的各个容器可以访问在Pod级别定义的Volumes。
好了,就说到这里,了解这么多我觉得就够了,再说会晕。
从头搭建k8s
这种搭建方式只有一种可能,就是本地传统玩家,教程网上一大堆,这里只介绍基本步骤:
- 准备几台虚拟机
- 配置主机名与静态IP
- 关闭防火墙
- 校正系统时间
- 关闭selinux
- 关闭swap
- IPv4流量传递到iptable
- 在所有节点安装Docker和Kubeadm和Kubelet和Kubectl
- 部署k8s master
- 部署Pod网络查件CNI
- 加入k8s Node
- 测试k8s集群
好似裹脚布,又臭又长,感觉每一步都可能缠住我的脖子,让我分分钟从入门到放弃。
EKS - managed k8s on aws
aws 托管的k8s服务(目前更新到1.15),中国区可用,是一项完全托管的 Kubernetes 服务。出于其安全性、可靠性和可扩展性,Intel、Snap、Intuit、GoDaddy 和 Autodesk 等客户都在使用它来运行他们最敏感的任务关键型应用程序。
EKS有几个特性:
- 托管:两个字,省心,多活几年。
- 自动高可用:可跨多个 AWS 可用区运行 Kubernetes 管理基础设施、自动检测和替换运行状况不佳的控制平面节点,并提供零停机时间的按需升级和修补
- 提供无服务器选项 - 支持 AWS Fargate 为容器提供无服务器计算功能。使用 Fargate,您无需预置和管理服务器,而且可以为每个应用程序指定资源并为其付费,并通过设计隔离应用程序来提高安全性。
- 安全:自动将最新的安全补丁应用到您的集群控制平面。AWS 还与社区紧密合作,以确保在将新版本和补丁部署到现有集群之前解决关键的安全问题。
- 通过社区构建:可运行上游 Kubernetes,且经认证可与 Kubernetes 兼容,因此 EKS 托管的应用程序与所有标准 Kubernetes 环境托管的应用程序完全兼容。AWS 主动与 Kubernetes 社区合作,其中包括为 Kubernetes 代码库做贡献,以帮助您充分利用 AWS 服务和功能。
EKS部署有三种方式:
- AWS 控制台 - 鼠标点点点
- eksctl 命令行
- CloudFormation/CDK
好了,了解到这里也够了,否则就不叫托管了。
一键创建EKS集群(k8s)
-
准备工作是要确认你现在执行命令的shell具不具备以下条件:
-
是否安装并配置好最新的 AWSCLI2
-
是否安装了eksctl
-
是否安装了 Kubectl
-
如果答案都是yes,那么执行eksctl命令一键部署EKS:
$ eksctl create cluster \
> --name myeks \
> --version 1.15 \
> --region cn-northwest-1 \
> --nodegroup-name workers \
> --node-type m5.large \
> --nodes 3 \
> --managed
[ℹ] eksctl version 0.15.0
[ℹ] using region cn-northwest-1
[ℹ] setting availability zones to [cn-northwest-1c cn-northwest-1a cn-northwest-1b]
[ℹ] subnets for cn-northwest-1c - public:192.168.xx.xx/19 private:192.168.xx.xx/19
[ℹ] subnets for cn-northwest-1a - public:192.168.xx.xx/19 private:192.168.xx.xx/19
[ℹ] subnets for cn-northwest-1b - public:192.168.xx.xx/19 private:192.168.xx.xx/19
[ℹ] using Kubernetes version 1.15
[ℹ] creating EKS cluster "myeks" in "cn-northwest-1" region with managed nodes
[ℹ] will create 2 separate CloudFormation stacks for cluster itself and the initial managed nodegroup
[ℹ] if you encounter any issues, check CloudFormation console or try 'eksctl utils describe-stacks --region=cn-northwest-1 --cluster=myeks'
[ℹ] CloudWatch logging will not be enabled for cluster "myeks" in "cn-northwest-1"
[ℹ] you can enable it with 'eksctl utils update-cluster-logging --region=cn-northwest-1 --cluster=myeks'
[ℹ] Kubernetes API endpoint access will use default of {publicAccess=true, privateAccess=false} for cluster "myeks" in "cn-northwest-1"
[ℹ] 2 sequential tasks: { create cluster control plane "myeks", create managed nodegroup "workers" }
[ℹ] building cluster stack "eksctl-myeks-cluster"
[ℹ] deploying stack "eksctl-myeks-cluster"
[ℹ] building managed nodegroup stack "eksctl-myeks-nodegroup-workers"
[ℹ] deploying stack "eksctl-myeks-nodegroup-workers"
[✔] all EKS cluster resources for "myeks" have been created
[✔] saved kubeconfig as "C:\\Users\\xxx/.kube/config"
[ℹ] nodegroup "workers" has 3 node(s)
[ℹ] node "ip-192-168-xx-xx.cn-northwest-1.compute.internal" is ready
[ℹ] node "ip-192-168-xx-xx.cn-northwest-1.compute.internal" is ready
[ℹ] node "ip-192-168-xx-xx.cn-northwest-1.compute.internal" is ready
[ℹ] waiting for at least 3 node(s) to become ready in "workers"
[ℹ] nodegroup "workers" has 3 node(s)
[ℹ] node "ip-192-168-xx-xx.cn-northwest-1.compute.internal" is ready
[ℹ] node "ip-192-168-xx-xx.cn-northwest-1.compute.internal" is ready
[ℹ] node "ip-192-168-xx-xx.cn-northwest-1.compute.internal" is ready
[ℹ] kubectl command should work with "C:\\Users\\xxx/.kube/config", try 'kubectl get nodes'
[✔] EKS cluster "myeks" in "cn-northwest-1" region is ready
这样默认部署的集群架构长这样,当然后期我也可以看eks文档按照我实际工作调整:
- 进AWS console的EKS服务看下,myeks已经创建好了!点进去看到,3个搬砖工已经ready!
PS: 其实呢,一键部署背后还是调用了AWS的自动化部署神器 - CloudFormation
- 如果我不想所有资源都新建,而是把集群放在现有的VPC下,那就加上这些选项:
--vpc-public-subnets public_subnet_1a, public_subnet_1b \
--vpc-private-subnets private_subnet_1a, prviate_subnet_1b \
- 其他选项:
--ssh-public-key eks-bjs # 指定现有的pem文件
--node-ami ami-xxxx # 可以指定自己的ami, but --managed unable to used
--node-ami-family # 指定OS系统, default is Amazon Linux 2
# AmazonLinux2, Ubuntu1804, WindowsServer2019FullContainer, WindowsServer2019CoreContainer
$ AWS_PROFILE=bjs # 指定用哪个aksk身份来创建集群 cat ~/.aws/config 可以看
管理EKS
- 在本机用awscli把EKS集群的信息同步到
kubeconfig
文件。
$ aws eks update-kubeconfig --name <cluster_name>
例如:
$ aws eks update-kubeconfig --name myeks
Added new context arn:aws-cn:eks:cn-northwest-1:xxxxxxxxxxxx:cluster/myeks to C:\Users\xxxx\.kube\config
- 查看nodes:
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
ip-192-168-xx-xx.cn-northwest-1.compute.internal Ready <none> 7m55s v1.15.10-eks-bac369
ip-192-168-xx-xx.cn-northwest-1.compute.internal Ready <none> 7m49s v1.15.10-eks-bac369
ip-192-168-xx-xx.cn-northwest-1.compute.internal Ready <none> 7m41s v1.15.10-eks-bac369
部署应用
- 这里我们整个最简单的web服务nginx测试下吧,新建一个dockerfile,这个功能很简单,就是提供一个web服务器,然后页面显示 “ Hello, Docker!”。
$ vim dockerfile
FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
- 在aws console的ECR里新建一个镜像仓库,用来存放镜像。记住,aws上所有的镜像都是注册在ECR上统一管理的,让我想起了某云的容器居然就直接丢在对象存储里,葬爱家族轻狂不羁。
- 创建本机docker并注册到ECR的镜像仓库里。
$ docker build . -t xxxxxxxxxxx.dkr.ecr.cn-northwest-1.amazonaws.com.cn/ekstest
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
xxxxxxxxxxx.dkr.ecr.cn-northwest-1.amazonaws.com.cn/ekstest latest fef472de0787 47 hours ago 127MB
nginx latest ed21b7a8aee9 2 weeks ago 127MB
$ aws ecr get-login-password --region cn-northwest-1 | docker login --username AWS --password-stdin xxxxxxxxxxx.dkr.ecr.cn-northwest-1.amazonaws.com.cn/ekstest
Login Succeeded
$ docker push xxxxxxxxxxx.dkr.ecr.cn-northwest-1.amazonaws.com.cn/ekstest:latest
可以看到这个docker已经推到仓库了。
- 接下来创建YAML文件并用kubectl部署。
创建YAML文件 nginx-deployment.yaml
, 部署nginx
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: <account_id>.dkr.ecr.cn-northwest-1.amazonaws.com.cn/ekstest:latest # 自行修改ID
ports:
- containerPort: 80
$ kubectl.exe apply -f nginx-deployment.yaml
deployment.apps/nginx-deployment created
$ kubectl.exe get pods
NAME READY STATUS RESTARTS AGE
nginx-deployment-75d669445d-k2nqg 1/1 Running 0 2m46s
nginx-deployment-75d669445d-x6z7d 1/1 Running 0 2m46s
nginx-deployment-75d669445d-xdfdx 1/1 Running 0 2m46s
创建YAML文件 nginx-svc-nlb.yaml
,部署类型为负载均衡器的service (AWS Network Load Balance 服务)
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
spec:
type: LoadBalancer
selector:
app: nginx
ports:
- protocol: TCP
name: http
port: 80
targetPort: 80
$ kubectl.exe apply -f nginx-svc-nlb.yaml
service/nginx-svc created
$ kubectl.exe get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.100.0.1 <none> 443/TCP 51m
nginx-svc LoadBalancer 10.100.179.159 a9d4exxxxxxxxxxxxxxxxxxxxxx-dd11xxxxxxx.elb.cn-northwest-1.amazonaws.com.cn 80:30428/TCP 30s
可以看到负载均衡器已经起来了,我们在aws console中可以看到负载均衡器状态从 provisioning 变成 active 。
- 用网页打开LoadBalancer的DNS地址
a9d4exxxxxxxxxxxxxxxxxxxxxx-dd11xxxxxxx.elb.cn-northwest-1.amazonaws.com.cn
,看到了什么?
关于k8s里的IP地址
Kubernetes集群里有三种IP地址,分别如下:
- Node IP:Node节点的IP地址,即物理网卡的IP地址。
- Pod IP:Pod的IP地址,即docker容器的IP地址,此为虚拟IP地址。
- Cluster IP:Service的IP地址,此为虚拟IP地址。
学习链接
人生苦短,我用托管。