电子商务网站开发 当当网,室内设计学校网站,西安建筑公司网站建设,百度蜘蛛池Kubernetes简介Kubernetes是Google基于Borg开源的容器编排调度引擎#xff0c;作为CNCF#xff08;Cloud Native Computing Foundation#xff09;最重要的组件之一#xff0c;它的目标不仅仅是一个编排系统#xff0c;而是提供一个规范#xff0c;可以让你来描述集群的架… Kubernetes简介Kubernetes是Google基于Borg开源的容器编排调度引擎作为CNCFCloud Native Computing Foundation最重要的组件之一它的目标不仅仅是一个编排系统而是提供一个规范可以让你来描述集群的架构定义服务的最终状态Kubernetes可以帮你将系统自动得达到和维持在这个状态。更直白的说Kubernetes可以让用户通过编写一个yaml或者json格式的配置文件也可以是通过工具/代码生成或者是直接请求Kubernetes API来创建应用该配置文件中包含了用户想要应用程序保持的状态不管整个Kubernetes集群中的个别主机发生什么问题都不会影响应用程序的状态你还可以通过改变该配置文件或请求Kubernetes API来改变应用程序的状态。这意味着开发人员不需要在意节点的数目也不需要在意从哪里运行容器以及如何与它们交流。开发人员也不需要管理硬件优化或担心节点关闭它们将遵循墨菲法则因为新的节点会添加到Kubernetes集群同时Kubernetes会在其他运行的节点中添加容器Kubernetes会发挥最大的作用。总结Kubernetes是容器控制平台可以抽象所有的底层基础设施容器运行用到的基础设施。Kubernetes——让容器应用进入大规模工业生产。Kubernetes另一个深入人心的特点是它标准化了云服务提供商。比如有一个Azure、Google云平台或其他云服务提供商的专家他担任了一个搭建在全新的云服务提供商的项目。这可能引起很多后果比如说他可能无法在截止期限内完成公司可能需要招聘更多相关的人员等等。相对的Kubernetes就没有这个问题。因为不论是哪家云服务提供商你都可以在上面运行相同的命令以既定的方式向Kubernetes API服务器发送请求Kubernetes会负责抽象并在不同的云服务商中实现。对于公司来说这意味着他们不需要绑定到任何一家云服务商。他们可以计算其他云服务商的开销然后转移到别家并依旧保留着原来的专家原来的人员他们还可以花更少的钱。PodKubernetes有很多技术概念同时对应很多API对象最重要的也是最基础的对象就是Pod。Pod是Kubernetes集群中运行部署应用的最小单元并且是支持多个容器的。Pod的设计理念是支持多个容器在一个Pod中共享网络地址和文件系统可以通过进程间通信和文件共享这种简单高效的方式组合完成服务。Pod对多容器的支持是Kubernetes最基础的设计理念。比如你运行一个操作系统发行版的软件仓库一个Nginx容器用来发布软件另一个容器专门用来从源仓库做同步这两个容器的镜像不太可能是一个团队开发的但是他们一块儿工作才能提供一个微服务这种情况下不同的团队各自开发构建自己的容器镜像在部署的时候组合成一个微服务对外提供服务。不过在大多数情况下我们只会在Pod中运行一个容器本文中的例子也是这样的。Pod 的另一个特征是如果我们希望使用其他 RKE 等技术的话我们可以做到不依赖Docker容器。Docker是kubernetes中最常用的容器运行时但是Pod也支持其他容器运行时。总的来说Pod的主要特征包括每个Pod可以在Kubernetes集群内拥有唯一的IP地址Pod可以拥有多个容器。这些容器共享同一个端口空间所以他们可以通过localhost交流可想而知它们无法使用相同的端口与其他Pod内容器的交流可以通过结合Pod的IP来完成一个Pod内的容器共享同一个卷、同一个 IP、端口空间、IPC 命名空间。定义一个Pod如下我们定义一个最简单的PodapiVersion: v1kind: Pod # 定义Kubernetes资源的类型为Podmetadata: name: demo-web # 定义资源的名称 labels: # 为Pod贴上标签后面会介绍其用处 app: demo-webspec: # 定义资源的状态对于Pod来说最重要属性就是containers containers: # containers一个数组类型如果你希望部署多个容器可以添加多项 - name: web # 定义本Pod中该容器的名称 image: rainingnight/aspnetcore-web # 定义Pod启动的容器镜像地址 ports: - containerPort: 80 # 定义容器监听的端口与Dockerfile中的EXPOSE类似只是为了提供文档信息然后保存我这里命名为demo-web-pod.yaml。现在我们可以在终端中输入以下命令来创建该Podkubectl create -f demo-web-pod.yaml# 输出# pod/demo-web created可以使用如下命令来查看kubernetes中的Pod列表:kubectl get pods# 输出# NAME READY STATUS RESTARTS AGE# demo-web 1/1 Running 0 65s如果该Pod还处于ContainerCreating状态的话你可以在运行命令的时候加入--watch参数这样当Pod变成运行状态的时候会自动显示在终端中。访问应用程序在上面我们成功部署了一个ASP.NET Core Mvc程序的Pod那么如何访问它呢如果只是为了调试我们可以使用转发端口的方式来快速访问kubectl port-forward demo-web 8080:80# 输出# Forwarding from 127.0.0.1:8080 - 80然后我们再浏览器中访问127.0.0.1:8080显示如下如上还展示了Pod的主机名和IP这是因为我在应用中添加了如下代码public void OnGet(){HostName Dns.GetHostName();HostIP Dns.GetHostEntry(HostName).AddressList.FirstOrDefault(x x.AddressFamily AddressFamily.InterNetwork).ToString();
}不过端口转发的方式只能在本机访问为了从外部访问应用程序我们需要创建Kubernetes中的另外一种资源Service。ServiceKubernetes中的Service资源可以作为一组提供相同服务的Pod的入口这个资源肩负发现服务和平衡Pod之间负荷的重任。在Kubernetes集群中我们拥有提供不同服务的Pod那么Service如何知道该处理哪个Pod呢这个问题就用标签来解决的具体分两个步骤给所有需要Service处理的对象Pod贴上标签。在Service中使用一个选择器Label Selector该选择器定义了所有贴有对应的标签的对象Pod。标签标签提供了一种简单的方法用于管理Kubernetes中的资源。它们用一对键值表示且可以用于所有资源。其实在上面的Pod定义中我们已经定义了标签metadata: name: demo-web labels: app: demo-web如上我们为Pod附加了标签app:demo-web在查看Pod的时候可以使用--show-labels参数来显示Pod对应的标签kubectl get pods --show-labels# 输出# NAME READY STATUS RESTARTS AGE LABELS# demo-web 1/1 Running 0 1m52s appdemo-web可以看到我们的Pod都拥有一个appdemo-web标签。定义Service现在让我们为刚才创建的Pod定义一个ServiceapiVersion: v1kind: Service # 定义Kubernetes资源的类型为Servicemetadata: name: demo-web-service # 定义资源的名称spec: selector: # 指定对应的Pod app: demo-web # 指定Pod的标签为demo-web ports: - protocol: TCP # 协议类型 port: 80 # 指定Service访问的端口 targetPort: 80 # 指定Service转发请求的端口 nodePort: 30000 type: NodePort # 指定Service的类型在这里使用NodePort来对外访问如上我们使用selector属性来选择相应的标签并把服务类型type设置为NodePorttype的取值有以下4种ClusterIP默认值通过集群的内部IP暴露服务该模式下服务只能够在集群内部可以访问。NodePort通过每个Node上的IP和静态端口NodePort暴露服务NodePort服务会路由到ClusterIP服务这个ClusterIP服务会自动创建。LoadBalancer使用云提供商的负载均衡器可以向外部暴露服务外部的负载均衡器可以路由到NodePort服务和ClusterIP服务。ExternalName通过返回CNAME和它的值可以将服务映射到externalName字段的内容如foo.bar.example.com。没有任何类型代理被创建这只有 Kubernetes 1.7 或更高版本的kube-dns才支持。对于服务类型我们先了解这么多就可以了后续会再来详细介绍。然后使用如下命令创建Servicekubectl create -f demo-web-service.yaml# 输出# service/demo-web-service created使用如下命令来检查服务的状态kubectl get services# 输出# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE# demo-web-service NodePort 10.105.132.214 none 80:30000/TCP 10s如上它有一个CLUSTER-IP为10.105.132.214因此我们可以在集群内使用10.105.132.214:80来访问该服务如果是在集群外部可以使用NodeIP:30000来访问。服务发现与负载均衡在上面我们说到Service肩负着发现服务和平衡Pod之间负荷的重任那它是怎么做的呢让我们先再添加一个PodapiVersion: v1kind: Podmetadata: name: demo-web-copy labels: app: demo-webspec: containers: - name: web image: rainingnight/aspnetcore-web ports: - containerPort: 80如上其定义与之前的Pod一样只是把name改成了demo-web-copy然后创建Pod:kubectl create -f demo-web-copy.pod.yaml# 查看Podkubectl get pods# 输出# NAME READY STATUS RESTARTS AGE# demo-web 1/1 Running 0 10m# demo-web-copy 1/1 Running 0 29s现在我们使用NodeIP:30000来访问打开两个浏览器窗口多刷新几次以便让它们分别路由到不同的Pod最终显示如下可以看到我们新创建的Pod已经通过Servie来接受请求了不需要修改成任何程序代码Kubernetes就已经帮我们实现了服务发现和负载均衡是不是非常爽。Deployment在上面我们手动部署了两个Pod但是这只是单机的玩法它与直接使用Docker容器相比并无太大优势如果我们需要部署一千个实例那就是一个痛苦的过程或者我们又想快速更新和迅速回滚这根本就是不可能的其实在k8s中我们很少直接使用Pod更多的是使用Kubernetes的另外一种资源Deployment。Deployment表示用户对Kubernetes集群的一次更新操作。可以是创建一个新的服务或是更新一个新的服务也可以是滚动升级一个服务。Deployment可以帮助每一个应用程序的生命都保持相同的一点那就是变化。此外只有挂掉的应用程序才会一尘不变否则新的需求会源源不断地涌现更多代码会被开发出来、打包以及部署这个过程中的每一步都有可能出错。Deployment可以自动化应用程序从一版本升迁到另一版本的过程并保证服务不间断如果有意外发生它可以让我们迅速回滚到前一个版本。Deployment定义现在我们使用Deployment来部署我们的Pod并实现在部署期间服务不间断服务可以如下定义apiVersion: apps/v1kind: Deployment # 定义Kubernetes资源的类型为Deploymentmetadata: name: demo-web-deployment # 定义资源的名称 labels: app: demo-web-deploymentspec: # 定义资源的状态。 replicas: 2 # 定义我们想运行多少个Pod在这里我们希望运行2个 selector: matchLabels: # 定义该部署匹配哪些Pod app: demo-web minReadySeconds: 5 # 可选指定Pod可以变成可用状态的最小秒数默认是0 strategy: # 指定更新版本时部署使用的策略 type: RollingUpdate # 策略类型使用RollingUpdate可以保证部署期间服务不间断 rollingUpdate: maxUnavailable: 1 # 部署时最大允许停止的Pod数量与replicas相比 maxSurge: 1 # 部署时最大允许创建的Pod数量与replicas相比 template: # 用来指定Pod的模板与Pod的定义类似 metadata: labels: # 根据模板创建的Pod会被贴上该标签与上面的matchLabels对应 app: demo-web spec: containers: - name: web image: rainingnight/aspnetcore-web imagePullPolicy: Always # 默认是IfNotPresent如果设置成Always则每一次部署都会重新拉取容器映像否则如果本地存在指定的镜像版本就不会再去拉取 ports: - containerPort: 80保存为demo-web-deployment.yaml然后输入以下命令来创建Deploymentkubectl create -f demo-web-deployment.yaml# 输出# deployment.apps/demo-web-deployent created现在我们再来查看以下Pod:kubectl get pods# 输出# NAME READY STATUS RESTARTS AGE# demo-web 1/1 Running 0 4h28m# demo-web-copy 1/1 Running 0 18m# demo-web-deployment-745f7997c4-d24bb 1/1 Running 0 16s# demo-web-deployment-745f7997c4-jk9jn 1/1 Running 0 16s如上我们有4个运行中的Pod其中前二个是我们手动创建的其他两个是使用Deployment创建的。我们可以使用kubectl delete pod pod-name删除一个Deployment创建的Pod看看结果会怎样kubectl delete pod demo-web-deployment-745f7997c4-d24bb# 输出# pod demo-web-deployment-745f7997c4-d24bb deleted再次查看Pod列表kubectl get pods# 输出# NAME READY STATUS RESTARTS AGE# demo-web 1/1 Running 0 31m# demo-web-copy 1/1 Running 0 22m# demo-web-deployment-745f7997c4-jk9jn 1/1 Running 0 3m39s# demo-web-deployment-745f7997c4-mrrw6 1/1 Running 0 11s可以看到又重新创建了一个Poddemo-web-deployment-745f7997c4-mrrw6Deployment会监控我们的Pod数量保持为我们预期的个数。零停机时间部署(Zero-downtime)现在我们尝试以下零停机部署首先修改Deployment中的image为rainingnight/aspnetcore-web:1.0.0然后运行如下命令kubectl apply -f demo-web-deployment.yaml --record# 输出# deployment.apps/demo-web-deployment configured将kubectl的--record设置为true可以在annotation中记录当前命令创建或者升级了该资源。这在未来会很有用例如查看在每个 Deployment revision 中执行了哪些命令。除了修改yaml外还可以直接运行kubectl set image deployment demo-web-deployment webrainingnight/aspnetcore-web:1.0.0 --record来达到同样的效果。然后使用如下命令检查服务更新状态kubectl rollout status deployment demo-web-deployment# 输出# Waiting for deployment demo-web-deployment rollout to finish: 1 old replicas are pending termination...# Waiting for deployment demo-web-deployment rollout to finish: 1 old replicas are pending termination...# Waiting for deployment demo-web-deployment rollout to finish: 1 old replicas are pending termination...# Waiting for deployment demo-web-deployment rollout to finish: 1 old replicas are pending termination...# Waiting for deployment demo-web-deployment rollout to finish: 1 of 2 updated replicas are available...# Waiting for deployment demo-web-deployment rollout to finish: 1 of 2 updated replicas are available...# deployment demo-web-deployment successfully rolled out如上可以看到新版本已经成功上线并在这个过程中副本被逐个替换也就意味着应用程序始终在线。现在我们刷新一下浏览器可以看到标题已经变成了Home page - Web-v1:回滚到前一个状态如果突然发现新上线的版本有Bug需要紧急回滚到上一个版本那对Kubernetes来说也是非常简单的。我们首先运行如下命令来查看历史版本kubectl rollout history deployment demo-web-deployment# 输出# deployment.extensions/demo-web-deployment # REVISION CHANGE-CAUSE# 1 none# 2 kubectl apply --filenamedemo-web-deployment.yaml --recordtrue如上可以看到有2条历史那么为什么第1条的CHANGE-CAUSE是none呢这就是因为我们第二次部署的时候使用了--recordtrue参数。现在我们想回滚到第一个版本只需运行如下命令kubectl rollout undo deployment demo-web-deployment --to-revision1# 输出# deployment.extensions/demo-web-deployment rolled back再次刷新浏览器标题又变回了Home page - Web。部署多个应用现在我们再部署一个ASP.NET Core WebApi程序并在刚才的Web应用中调用它形成一个最简单的微服务模式。部署WebApi与前面的Web应用的部署类似就不用过多介绍定义如下YAML:apiVersion: apps/v1kind: Deploymentmetadata: name: demo-api-deployment labels: app: demo-api-deploymentspec: replicas: 2 selector: matchLabels: app: demo-api minReadySeconds: 5 strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 1 maxSurge: 1 template: metadata: labels: app: demo-api spec: containers: - name: api image: rainingnight/aspnetcore-api imagePullPolicy: Always ports: - containerPort: 80然后创建Deploymentkubectl create -f demo-api-deployment.yaml 查看部署情况kubectl get pods# 输出# NAME READY STATUS RESTARTS AGE# demo-api-deployment-66575d644-9wk7g 1/1 Running 0 75s# demo-api-deployment-66575d644-fknpx 1/1 Running 0 75s# demo-web-deployment-745f7997c4-h7fr8 1/1 Running 0 9m23s# demo-web-deployment-745f7997c4-kvptm 1/1 Running 0 9m23s前面手动创建的2个Pod已经被我删除了因为用Deployment创建的Pod就好了。现在我们为Api应用也创建一个Service以便在Web应用中访问它apiVersion: v1kind: Servicemetadata: name: demo-api-servicespec: selector: app: demo-api ports: - protocol: TCP port: 80 targetPort: 80因为我们的Api应用是不需要在集群外部访问的因此服务类型type不需要设置使用默认的ClusterIP就可以了。部署Servcie:kubectl create -f demo-api-service.yaml然后查看Servie:kubectl get services# 输出# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE# demo-api-service ClusterIP 10.111.25.49 none 80/TCP 26s# demo-web-service NodePort 10.105.132.214 none 80:30000/TCP 58m可以使用浏览器来访问10.111.25.49/api/values 来验证一下是否部署成功。调用服务那么还剩下最后一个问题我们的Web应用中如何获取到Api应用的访问地址呢我们先看一下在Web应用的代码中是怎么调用Api的// Startup.cspublic void ConfigureServices(IServiceCollection services){services.AddHttpClient(api, _ _.BaseAddress new Uri(Configuration[ApiBaseUrl]));
}// FetchData.cshtmlpublic class FetchDataModel : PageModel{ private static HttpClient _client; public FetchDataModel(IHttpClientFactory httpClientFactory) {_client httpClientFactory.CreateClient(api);} public IListWeatherForecast Forecasts { get; set; } public async Task OnGetAsync() { var res await _client.GetStringAsync(/api/SampleData/WeatherForecasts);Forecasts JsonConvert.DeserializeObjectIListWeatherForecast(res);}
}如上我们首先注册了一个HttpClient并从配置文件中读取ApiBaseUrl做为BaseAddress然后在FetchData页面中使用HttpClient调用Api服务。因为在Asp.Net Core中默认情况下环境变量中的配置是会覆盖appsettings.json中的配置的因此我们可以使用添加环境变量的方式来配置ApiBaseUrl。修改demo-web-deployment.yaml添加env属性如下containers: - name: web image: rainingnight/aspnetcore-web imagePullPolicy: Always ports: - containerPort: 80 env: - name: ApiBaseUrl value: http://10.111.25.49然后在Kubernetes中应用该配置kubectl apply -f demo-web-deployment.yaml 等待滚动更新完成刷新浏览器点击FetchData菜单上可以看到数据成功返回但是直接使用集群IP10.111.25.49这也有点太低级了其实我们可以直接使用域名http://demo-api-service修改后如下 env: - name: ApiBaseUrl value: http://demo-api-service提交到Kubernetes然后刷新浏览器可以看到完美运行这是因为CoreDNS(Kube-DNS)帮我们完成了域名解析。在Kubernetes 1.11中CoreDNS已经实现了基于DNS的服务发现的GA可作为kube-dns插件的替代品。这意味着CoreDNS将作为各种安装工具未来发布版本中的一个选项来提供。事实上kubeadm团队选择将其作为Kubernetes 1.11的默认选项。CoreDNS是一个通用的、权威的DNS服务器提供与Kubernetes后向兼容但可扩展的集成。它解决了kube-dns所遇到的问题并提供了许多独特的功能可以解决各种各样的用例。DNS服务器监控kubernetes创建服务的API, 并为每个服务创建一组dns记录。如果在整个群集中启用了dns, 所有Pod都会使用它作为DNS服务器。比如我们的demo-api-service服务DNS服务器会创建一条my-service.my-ns也就是10.111.25.49:demo-api-service.default的dns记录因为我们的Web应用和Api应用在同一个命名空间(default)中所以可以直接使用demo-api-service来访问。总结本文带领大家一步一步部署了一个最简单的ASP.NET Core MVC WebApi的微服务程序介绍了Kubernetes中最基本的三个概念PodDeploymentService相信大家对Kubernetes也有了一个全面的认识。虽然Kubernetes整个体系是非常复杂的但是不用担心一开始我们不用去求甚解最重要的是先跑起来后续我会和大家一起逐步深入由简到繁愉快的掌握Kubernetes。附本文所用示例代码https://github.com/RainingNight/AspNetCoreDocker。相关资料Kubernetes Concepts使用Kubeadm(1.13)快速搭建Kubernetes集群kubernetes-dashboard(1.8.3)部署与踩坑原文地址:https://www.cnblogs.com/RainingNight/p/first-aspnetcore-app-in-k8s.html.NET社区新闻深度好文欢迎访问公众号文章汇总 http://www.csharpkit.com