背景
接上一篇 Windows 应用容器 后, 想要快速且便利的部署与管理它们, 可以借助容器编排工具. 对于 Windows 容器, 在今天 Service Fabric 会是个更为成熟的选择, 在业界有更多的实践案例. 笔者未来可能会写几篇关于如何使用 Service Fabric 来实现 Windows 平台下的微服务实践. 此次我们接着上篇的内容往下去快速搭建 Windows Kubernetes 环境.
ACS-Engine
Azure 团队为容器编排引擎提供了一个开源的部署工具 https://GitHub.com/Azure/acs-engine , 它可以支持在 Azure 上快速部署 Swarm,DC\OS, Kubernetes 集群, 同时具备扩缩 Worker 节点, 升级等等. 这套工具的大体思路是, 利用 Azure Infrastructure 服务的可描述性, 声明计算 , 存储, 网络等服务, 同时实现 Kubernetes 与 Azure 整合, 从而达到利用一个工具快速部署管理 Kubernetes. 和我们使用 Terraform 类似, 只是 acs-engine 是一个和 Azure 集成更为紧密的一个工具, 使得这个 Kubernetes 可以利用 Azure CNI ,LoadBalancer 以及云磁盘存储以及云文件存储. 下图来源于 ACS-engine 官方说明:
再提一提 Azure CNI, 它是由 Azure 团队针基于 CNI 实现的容器网络技术, 利用 Azure SDN 的能力, 使得容器网络可以连接 Azure .NET. 因此使用 Azure CNI 可以:
Kubernetes 的容器网络和 Azure .NET 在一个平面之上, 不需要有 Overlay.
同一 Azure .NET 下的虚机也可以直接与 Kubernetes 容器互通, 不需要经过负载经衡器. 这个可以解决我们在微服务场景下, K8S 里的容器要与 此 K8S 集群之外的服务实例之间的通讯, 例如我们有 dubbo 或 spring cloud 混合部署的场景.
在网络传输效率和资源消耗上会比自己在 Azure 上搭一套使用 Flannel 的 Kubernetes 要好, 按照笔者的测试能提升 20%~30%.
对于 acs-engine 除了能支持原生 Kubernetes 具备的特性, 更多特性可以参考 [6] , 当然能也能支持 GPU 的机器
前提
安装 Azure CLI
安装 https://GitHub.com/Azure/acs-engine/releases
一个可用的 Azure 中国区的账号
步骤
通过 Azure CLI 登录 Azure 中国, 并且生成一个 Contributor 的操作身份给后续部署 K8S 时建立相关资源使用
- az cloud set --name AzureChinaCloud
- az login
- az account set --subscription="${SUBSCRIPTION_ID}"
- # 下一行命令会生成一个 service principal, 需要记录 appId 以及 password 留做后续使用
- az ad sp create-for-rbac --role="Contributor" --scopes="/subscriptions/${SUBSCRIPTION_ID}"
准备 acs-engine 的集群部署描述文件, 由于 JSON 文件不包含注释的语法, 为了能更好的理解下面的某些字段信息, 我还是用 # 作为注释符用于解释. 当实际操作时请删除相关 # 行目.
- {
- "apiVersion": "vlabs",
- # 部署区域
- "location": "chinanorth2",
- "properties": {
- "orchestratorProfile": {
- #指定编排引擎类型为 kubernetes
- "orchestratorType": "Kubernetes",
- # 指定版本
- "orchestratorRelease": "1.11",
- "kubernetesConfig": {
- # 该 kubernetes 集群将激活 rbac
- "enableRbac": true,
- # 该 kubernetes 集群将使用 Azure CNI 作为容器网络实现
- "networkPolicy": "azure"
- }
- },
- #指定 master 节点信息
- "masterProfile": {
- # 此处为 1 个 master 节点, 也可以声明为 3, 或者其奇数
- "count": 1,
- # 给定一个 DNS 前缀, 用于声明此 K8S 服务在 azure 中国北二区的子域名. 例如此处为: burn-k8s-11.chinanorth2.cloudapp.chinacloudapi.cn
- "dnsPrefix": "burn-k8s-11",
- # master 节点的型号
- "vmSize": "Standard_D3_v2"
- },
- # 指定 Node 节点列表, 可以声明多个, 不同机型分别是多少台, 分别用什么操作系统. 包括使用可用性集来做高可用性保证, 也能使用虚机扩展集
- "agentPoolProfiles": [
- {
- "name": "windowspool2",
- "count": 3,
- "vmSize": "Standard_D3_v2",
- "availabilityProfile": "AvailabilitySet",
- "osType": "Windows"
- }
- ],
- # 在 Windows Kubernetes 的环境里需要 master 仍为 Linux, 在 masterProfile 中未声明使用什么 OS, 默认是 Linux
- "linuxProfile": {
- #虚机登录用户名
- "adminUsername": "zhaw",
- "SSH": {
- "publicKeys": [
- {
- # 虚机登录使用的公钥
- "keyData": "SSH-rsa XXX"
- }
- ]
- }
- },
- # node 节点使用的 Windows 登陆信息
- "windowsProfile": {
- "adminUsername": "azureuser",
- "adminPassword": "XXX",
- "windowsPublisher": "MicrosoftWindowsServer",
- "windowsOffer": "WindowsServerSemiAnnual",
- "windowsSku": "Datacenter-Core-1803-with-Containers-smalldisk"
- },
- "servicePrincipalProfile": {
- #前面生成 service principal 的 appID
- "clientId": "XXX",
- #前面生成 service principal 的 password
- "secret": "XXX"
- }
- }
- }
使用 acs-engine 根据上述描述文件生成 ARM 的部署文件
- # 下面的命令将生成文件目录: _output/<dns_prefix>
- acs-engine generate kubernetes.JSON
在 output/<dnsprefix>/kubeconfig 目录下会生成连接到此 k8s 的 kubeconfig 文件, 我们只需要在本地安装 kubectl 就可以操作此集群, 不需要连到 Master 节点上操作
通过 azure CLI 创建一个资源管理库并在其中部署出 k8s
- # 进入到生成的文件目录
- cd _output/<dns_prefix>
- # 创建资源管理库
- az group create --name <GROUP_NAME> --location chinanorth2
- # 部署 k8s
- az group deployment create -g <GROUP_NAME> --template-file azuredeploy.JSON --parameters azuredeploy.parameters.JSON --verbose
部署完毕以后可以查看节点信息
- $ kubectl --kubeconfig=kubeconfig.chinanorth2.JSON get node --show-labels
- NAME STATUS ROLES AGE VERSION LABELS
- 35598k8s9000 Ready <none> 1h v1.11.2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/instance-type=Standard_D3_v2,beta.kubernetes.io/os=Windows,failure-domain.beta.kubernetes.io/region=chinanorth2,failure-domain.beta.kubernetes.io/zone=0,kubernetes.io/hostname=35598k8s9000
- 35598k8s9001 Ready <none> 1h v1.11.2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/instance-type=Standard_D3_v2,beta.kubernetes.io/os=Windows,failure-domain.beta.kubernetes.io/region=chinanorth2,failure-domain.beta.kubernetes.io/zone=0,kubernetes.io/hostname=35598k8s9001
- 35598k8s9002 Ready <none> 1h v1.11.2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/instance-type=Standard_D3_v2,beta.kubernetes.io/os=Windows,failure-domain.beta.kubernetes.io/region=chinanorth2,failure-domain.beta.kubernetes.io/zone=1,kubernetes.io/hostname=35598k8s9002
- k8s-master-35598902-0 Ready master 1h v1.11.2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/instance-type=Standard_D3_v2,beta.kubernetes.io/os=Linux,failure-domain.beta.kubernetes.io/region=chinanorth2,failure-domain.beta.kubernetes.io/zone=0,kubernetes.azure.com/cluster=wink8s,kubernetes.io/hostname=k8s-master-35598902-0,kubernetes.io/role=master
因为这个环境是一个 Linux 混合 Windows 的集群, 所以在部署 container 的时候需要指定节点类型, 好在 acs-engine 部署出来的集群节点上携带操作系统相关的 label
beta.kubernetes.io/os=Windows
, 我们可以通过 YAML 文件中使用 nodeSelector 来指定节点信息
- apiVersion: v1
- kind: Service
- metadata:
- name: stdlogclientwin
- labels:
- App: stdlogclientwin
- spec:
- ports:
- - port: 80
- name: http
- selector:
- App: stdlogclientwin
- type: LoadBalancer
- ---
- apiVersion: extensions/v1beta1
- kind: Deployment
- metadata:
- name: stdlogclientwin
- spec:
- replicas: 1
- template:
- metadata:
- labels:
- App: stdlogclientwin
- version: v1
- spec:
- containers:
- - name: stdlogclientwin
- image: burning1docker/stdlogclientwin:1803
- imagePullPolicy: IfNotPresent
- ports:
- - containerPort: 80
- volumeMounts:
- - name: hostsdir
- mountPath: "C:/Windows/System32/drivers/etc"
- nodeSelector:
- beta.kubernetes.io/os: Windows
- initContainers:
- - name: init
- image: microsoft/windowsservercore:1803
- command:
- - powershell
- - "Add-Content"
- - "-Path"
- - "C:/Windows/System32/drivers/etc/hosts"
- - "-Value"
- - "\"127.0.0.1 foo.local\""
- volumeMounts:
- - name: hostsdir
- mountPath: "C:/Windows/System32/drivers/etc"
- volumes:
- - name: hostsdir
- emptyDir: {}
从上面的示例文件中, 我们发现有一个通过 init container + emptyDir 来替换 hosts 的一个做法, 在 Linux 下可以用 HostAliases 来实现, 目前 Kubernetes Windows 上还不支持. 所以可以通过这种方式来实现.
另外我们还发现节点还携带了关于可用性集相关的信息, 所以我们还可以使用 pod anti-affinity 来把同一容器应用 Pod 平均部署到不同容错域, 以防 Azure 物理故障时导致容器在某一时刻不可用, 可参考如下示例:
- apiVersion: extensions/v1beta1
- kind: Deployment
- metadata:
- name: cpuloadv1
- spec:
- replicas: 3
- template:
- metadata:
- labels:
- App: cpuload
- version: v1
- spec:
- affinity:
- podAntiAffinity:
- preferredDuringSchedulingIgnoredDuringExecution:
- - weight: 100
- podAffinityTerm:
- labelSelector:
- matchExpressions:
- - key: App
- operator: In
- values:
- - cpuload
- topologyKey: failure-domain.beta.kubernetes.io/zone
- containers:
- - name: cpuload
- image: burning1docker/cpuload:V1
- imagePullPolicy: IfNotPresent
- ports:
- - containerPort: 8080
- resources:
- limits:
- CPU: "1"
- requests:
- CPU: 500m
提问
如何对 acs-engine 部署好的 k8s 集群扩 node 节点?
是否可以对 acs-engine 部署好的 k8s 降级?
对 acs-engine 部署好的 k8s 使用 Service Type 为 .LoadBalancer. 时, Azure LoadBalancer 的负载规则需要手动定义么?
- Ref:
- https://GitHub.com/Azure/acs-engine
- https://GitHub.com/Azure/acs-engine/releases
来源: https://www.cnblogs.com/bigdaddyblog/p/9712736.html