标签 k3s 下的文章

Manjaro 社区版 PinePhone Linux 智能机即将上市

Manjaro 团队表示:“PinePhone 的下一个社区版本(CE)将启用 Manjaro……现已支持几乎所有 Pine64 单板机和相关设备”。可购买预装了 Manjaro Linux 的 PinePhone,并且可从 2GB RAM + 16GB ROM / 3GB RAM + 32GB ROM 这两种存储组合中进行选择。

来源:cnbeta

拍一拍:真正的开源爱好者,自然希望他的手机也是真正开源的。

k3s 进入 CNCF 沙箱,首个进入 CNCF 的 k8s 发行版

Rancher 发布公告,宣布其开源项目 k3s 已经进入 CNCF 沙箱孵化。k3s 是一个轻量级 Kubernetes,适用于 Edge、IoT、CI 与 ARM 场景。k3s 旨在成为完全兼容的 Kubernetes 发行版。自 2019 年 2 月发布,k3s 的全球下载量超过 100 万次,每周平均被安装超过 2 万次,其中 30% 的下载量来自于中国。

来源:开源中国

拍一拍:虽然 k3s 像是一个 k8s 的子项目,但是还是被认为是独立项目进入了孵化。

Google Chrome 加入密码泄露检查功能,支持一键跳转修改

这项功能采用了“众所周知(.well-known)”的解决方案,大多数网站都有提供标准的“修改密码”页面。而 Chrome 浏览器做到了更进一步 —— 帮助用户一件跳转!

来源:cnbeta

拍一拍:为了你们泄露的密码,浏览器厂商真是操尽了心。

如何在树莓派上使用 k3s 和 Let's Encrypt 来加密你的网站。

上一篇文章中,我们在 k3s 集群上部署了几个简单的网站。那些是未加密的网站。不错,它们可以工作,但是未加密的网站有点太过时了!如今,大多数网站都是加密的。在本文中,我们将安装 cert-manager 并将其用于在集群上以部署采用 TLS 加密的网站。这些网站不仅会被加密,而且还会使用有效的公共证书,这些证书会从 Let's Encrypt 自动获取和更新!让我们开始吧!

准备

要继续阅读本文,你将需要我们在上一篇文章中构建的 k3s 树莓派集群。另外,你需要拥有一个公用静态 IP 地址,并有一个可以为其创建 DNS 记录的域名。如果你有一个动态 DNS 提供程序为你提供域名,可能也行。但是,在本文中,我们使用静态 IP 和 CloudFlare 来手动创建 DNS 的 A 记录。

我们在本文中创建配置文件时,如果你不想键入它们,则可以在此处进行下载。

我们为什么使用 cert-manager?

Traefik(在 k3s 预先捆绑了)实际上具有内置的 Let's Encrypt 支持,因此你可能想知道为什么我们要安装第三方软件包来做同样的事情。在撰写本文时,Traefik 中的 Let's Encrypt 支持检索证书并将其存储在文件中。而 cert-manager 会检索证书并将其存储在 Kubernetes 的 “ 机密信息 secret ” 中。我认为,“机密信息”可以简单地按名称引用,因此更易于使用。这就是我们在本文中使用 cert-manager 的主要原因。

安装 cert-manager

通常,我们只是遵循 cert-manager 的文档在 Kubernetes 上进行安装。但是,由于我们使用的是 ARM 体系结构,因此我们需要进行一些更改,以便我们可以完成这个操作。

第一步是创建 cert-manager 命名空间。命名空间有助于将 cert-manager 的 Pod 排除在我们的默认命名空间之外,因此当我们使用自己的 Pod 执行 kubectl get pods 之类的操作时,我们不必看到它们。创建名称空间很简单:

kubectl create namespace cert-manager

安装说明会让你下载 cert-manager 的 YAML 配置文件并将其一步全部应用到你的集群。我们需要将其分为两个步骤,以便为基于 ARM 的树莓派修改文件。我们将下载文件并一步一步进行转换:

curl -sL \
https://github.com/jetstack/cert-manager/releases/download/v0.11.0/cert-manager.yaml |\
sed -r 's/(image:.*):(v.*)$/\1-arm:\2/g' > cert-manager-arm.yaml

这会下载配置文件,并将包含的所有 docker 镜像更新为 ARM 版本。来检查一下它做了什么:

$ grep image: cert-manager-arm.yaml
          image: "quay.io/jetstack/cert-manager-cainjector-arm:v0.11.0"
          image: "quay.io/jetstack/cert-manager-controller-arm:v0.11.0"
          image: "quay.io/jetstack/cert-manager-webhook-arm:v0.11.0"

如我们所见,三个镜像现在在镜像名称上添加了 -arm。现在我们有了正确的文件,我们只需将其应用于集群:

kubectl apply -f cert-manager-arm.yaml

这将安装 cert-manager 的全部。我们可以通过 kubectl --namespace cert-manager get pods 来检查安装何时完成,直到所有 Pod 都处于 Running 状态。

这就完成了 cert-manager 的安装!

Let's Encrypt 概述

Let's Encrypt 的好处是,它免费为我们提供了经过公共验证的 TLS 证书!这意味着我们可以拥有一个完全有效的、可供任何人访问的 TLS 加密网站,这些家庭或业余的爱好活动挣不到钱,也无需自己掏腰包购买 TLS 证书!以及,当通过 cert-manager 使用 Let's Encrypt 的证书时,获得证书的整个过程是自动化的,证书的续订也是自动的!

但它是如何工作的?下面是该过程的简化说明。我们(或代表我们的 cert-manager)向 Let's Encrypt 发出我们拥有的域名的证书请求。Let's Encrypt 通过使用 ACME DNS 或 HTTP 验证机制来验证我们是否拥有该域。如果验证成功,则 Let's Encrypt 将向我们提供证书,这些证书将由 cert-manager 安装在我们的网站(或其他 TLS 加密的端点)中。在需要重复此过程之前,这些证书可以使用 90 天。但是,cert-manager 会自动为我们更新证书。

在本文中,我们将使用 HTTP 验证方法,因为它更易于设置并且适用于大多数情况。以下是幕后发生的基本过程。cert-manager 向 Let's Encrypt 发出证书请求。作为回应,Let's Encrypt 发出所有权验证的 质询 challenges 。这个质询是将一个 HTTP 资源放在请求证书的域名下的一个特定 URL 上。从理论上讲,如果我们可以将该资源放在该 URL 上,并且让 Let's Encrypt 可以远程获取它,那么我们实际上必须是该域的所有者。否则,要么我们无法将资源放置在正确的位置,要么我们无法操纵 DNS 以使 Let's Encrypt 访问它。在这种情况下,cert-manager 会将资源放在正确的位置,并自动创建一个临时的 Ingress 记录,以将流量路由到正确的位置。如果 Let's Encrypt 可以读到该质询要求的资源并正确无误,它将把证书发回给 cert-manager。cert-manager 将证书存储为“机密信息”,然后我们的网站(或其他任何网站)将使用这些证书通过 TLS 保护我们的流量。

为该质询设置网络

我假设你要在家庭网络上进行设置,并拥有一个以某种方式连接到更广泛的互联网的路由器/接入点。如果不是这种情况,则可能不需要以下过程。

为了使质询过程正常运行,我们需要一个我们要申请证书的域名,以将其路由到端口 80 上的 k3s 集群。为此,我们需要告诉世界上的 DNS 系统它的位置。因此,我们需要将域名映射到我们的公共 IP 地址。如果你不知道你的公共 IP 地址是什么,可以访问 WhatsMyIP 之类的地方,它会告诉你。接下来,我们需要输入 DNS 的 A 记录,该记录将我们的域名映射到我们的公共 IP 地址。为了使此功能可靠地工作,你需要一个静态的公共 IP 地址,或者你可以使用动态 DNS 提供商。一些动态 DNS 提供商会向你颁发一个域名,你可以按照以下说明使用它。我没有尝试过,所以不能肯定地说它适用于所有提供商。

对于本文,我们假设有一个静态公共 IP,并使用 CloudFlare 来设置 DNS 的 A 记录。如果愿意,可以使用自己的 DNS 服务器。重要的是你可以设置 A 记录。

在本文的其余部分中,我将使用 k3s.carpie.net 作为示例域名,因为这是我拥有的域。你显然会用自己拥有的任何域名替换它。

为示例起见,假设我们的公共 IP 地址是 198.51.100.42。我们转到我们的 DNS 提供商的 DNS 记录部分,并添加一个名为 k3s.carpie.net 的类型为 A 的记录(CloudFlare 已经假定了域的部分,因此我们只需输入 k3s),然后输入 198.51.100.42 作为 IPv4 地址。

请注意,有时 DNS 更新要传播一段时间。你可能需要几个小时才能解析该名称。在继续之前该名称必须可以解析。否则,我们所有的证书请求都将失败。

我们可以使用 dig 命令检查名称是否解析:

$ dig +short k3s.carpie.net
198.51.100.42

继续运行以上命令,直到可以返回 IP 才行。关于 CloudFlare 有个小注释:ClouldFlare 提供了通过代理流量来隐藏你的实际 IP 的服务。在这种情况下,我们取回的是 CloudFlare 的 IP,而不是我们的 IP。但对于我们的目的,这应该可以正常工作。

网络配置的最后一步是配置路由器,以将端口 80 和 443 上的传入流量路由到我们的 k3s 集群。可悲的是,路由器配置页面的差异很大,因此我无法确切地说明你的外观是什么样子。大多数时候,我们需要的管理页面位于“端口转发”或类似内容下。我甚至看到过它列在“游戏”之下(显然是端口转发主要用于的游戏)!让我们看看我的路由器的配置如何。

如果你和我的环境一样,则转到 192.168.0.1 登录到路由器管理应用程序。对于此路由器,它位于 “ NAT/QoS” -> “端口转发”。在这里,我们将端口 80/TCP 协议设置为转发到 192.168.0.50(主节点 kmaster 的 IP)的端口 80。我们还设置端口 443 也映射到 kmaster。从技术上讲,这对于质询来说并不是必需的,但是在本文的结尾,我们将部署一个启用 TLS 的网站,并且需要映射 443 来进行访问。因此,现在进行映射很方便。我们保存并应用更改,应该一切顺利!

配置 cert-manager 来使用 Let's Encrypt(暂存环境)

现在,我们需要配置 cert-manager 来通过 Let's Encrypt 颁发证书。Let's Encrypt 为我们提供了一个暂存(例如用于测试)环境,以便审视我们的配置。这样它更能容忍错误和请求的频率。如果我们对生产环境做了错误的操作,我们很快就会发现自己被暂时禁止访问了!因此,我们将使用暂存环境手动测试请求。

创建一个文件 letsencrypt-issuer-staging.yaml,内容如下:

apiVersion: cert-manager.io/v1alpha2
kind: ClusterIssuer
metadata:
  name: letsencrypt-staging
spec:
  acme:
    # The ACME server URL
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    # Email address used for ACME registration
    email: <your_email>@example.com
    # Name of a secret used to store the ACME account private key
    privateKeySecretRef:
      name: letsencrypt-staging
    # Enable the HTTP-01 challenge provider
    solvers:
    - http01:
        ingress:
          class: traefik

请确保将电子邮件地址更新为你的地址。如果出现问题或我们弄坏了一些东西,这就是 Let's Encrypt 与我们联系的方式!

现在,我们使用以下方法创建 发行者 issuer

kubectl apply -f letsencrypt-issuer-staging.yaml

我们可以使用以下方法检查发行者是否已成功创建:

kubectl get clusterissuers

clusterissuers 是由 cert-manager 创建的一种新的 Kubernetes 资源类型。

现在让我们手动请求一个测试证书。对于我们的网站,我们不需要这样做;我们只是在测试这个过程,以确保我们的配置正确。

创建一个包含以下内容的证书请求文件 le-test-certificate.yaml

apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
  name: k3s-carpie-net
  namespace: default
spec:
  secretName: k3s-carpie-net-tls
  issuerRef:
    name: letsencrypt-staging
    kind: ClusterIssuer
  commonName: k3s.carpie.net
  dnsNames:
  - k3s.carpie.net

该记录仅表示我们要使用名为 letsencrypt-staging(我们在上一步中创建的)的 ClusterIssuer 来请求域 k3s.carpie.net 的证书,并在 Kubernetes 的机密信息中名为 k3s-carpie-net-tls 的文件中存储该证书。

像平常一样应用它:

kubectl apply -f le-test-certificate.yaml

我们可以通过以下方式查看状态:

kubectl get certificates

如果我们看到类似以下内容:

NAME                    READY   SECRET                  AGE
k3s-carpie-net          True    k3s-carpie-net-tls      30s

我们走在幸福之路!(这里的关键是 READY 应该是 True)。

解决证书颁发问题

上面是幸福的道路。如果 READYFalse,我们可以等等它,然后再次花点时间检查状态。如果它一直是 False,那么我们就有需要解决的问题。此时,我们可以遍历 Kubernetes 资源链,直到找到一条告诉我们问题的状态消息。

假设我们执行了上面的请求,而 READYFalse。我们可以从以下方面开始故障排除:

kubectl describe certificates k3s-carpie-net

这将返回很多信息。通常,有用的内容位于 Events: 部分,该部分通常位于底部。假设最后一个事件是 Created new CertificateRequest resource "k3s-carpie-net-1256631848。然后我们 描述 describe 一下该请求:

kubectl describe certificaterequest k3s-carpie-net-1256631848

现在比如说最后一个事件是 Waiting on certificate issuance from order default/k3s-carpie-net-1256631848-2342473830

那么,我们可以描述该顺序:

kubectl describe orders default/k3s-carpie-net-1256631848-2342473830

假设有一个事件,事件为 Created Challenge resource "k3s-carpie-net-1256631848-2342473830-1892150396" for domain "k3s.carpie.net"。让我们描述一下该质询:

kubectl describe challenges k3s-carpie-net-1256631848-2342473830-1892150396

从这里返回的最后一个事件是 Presented challenge using http-01 challenge mechanism。看起来没问题,因此我们浏览一下描述的输出,并看到一条消息 Waiting for http-01 challenge propagation: failed to perform self check GET request ... no such host。终于!我们发现了问题!在这种情况下,no such host 意味着 DNS 查找失败,因此我们需要返回并手动检查我们的 DNS 设置,正确解析域的 DNS,并进行所需的任何更改。

清理我们的测试证书

我们实际上想要使用的是域名的真实证书,所以让我们继续清理证书和我们刚刚创建的机密信息:

kubectl delete certificates k3s-carpie-net
kubectl delete secrets k3s-carpie-net-tls

配置 cert-manager 以使用 Let's Encrypt(生产环境)

现在我们已经有了测试证书,是时候移动到生产环境了。就像我们在 Let's Encrypt 暂存环境中配置 cert-manager 一样,我们现在也需要对生产环境进行同样的操作。创建一个名为 letsencrypt-issuer-production.yaml 的文件(如果需要,可以复制和修改暂存环境的文件),其内容如下:

apiVersion: cert-manager.io/v1alpha2
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
 # The ACME server URL
  server: https://acme-v02.api.letsencrypt.org/directory
  # Email address used for ACME registration
  email: <your_email>@example.com
  # Name of a secret used to store the ACME account private key
  privateKeySecretRef:
    name: letsencrypt-prod
  # Enable the HTTP-01 challenge provider
  solvers:
  - http01:
      ingress:
        class: traefik

(如果要从暂存环境进行复制,则唯一的更改是 server: URL。也请不要忘记修改电子邮件!)

应用它:

kubectl apply -f letsencrypt-issuer-production.yaml

申请我们网站的证书

重要的是需要注意,我们到目前为止完成的所有步骤都只需要进行一次!而对于将来的任何其他申请,我们可以从这个说明开始!

让我们部署在上一篇文章中部署的同样站点。(如果仍然可用,则可以修改 YAML 文件。如果没有,则可能需要重新创建并重新部署它)。

我们只需要将 mysite.yamlIngress 部分修改为:

---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: mysite-nginx-ingress
  annotations:
    kubernetes.io/ingress.class: "traefik"
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  rules:
  - host: k3s.carpie.net
    http:
      paths:
      - path: /
        backend:
          serviceName: mysite-nginx-service
          servicePort: 80
  tls:
  - hosts:
    - k3s.carpie.net
    secretName: k3s-carpie-net-tls

请注意,上面仅显示了 mysite.yamlIngress 部分。所做的更改是添加了注解 cert-manager.io/cluster-issuer: letsencrypt-prod。这告诉 traefik 创建证书时使用哪个发行者。 其他唯一增加的是 tls: 块。这告诉 traefik 我们希望在主机 k3s.carpie.net 上具有 TLS 功能,并且我们希望 TLS 证书文件存储在机密信息 k3s-carpie-net-tls 中。

请记住,我们没有创建这些证书!(好吧,我们创建了名称相似的测试证书,但我们删除了这些证书。)Traefik 将读取这些配置并继续寻找机密信息。当找不到时,它会看到注释说我们想使用 letsencrypt-prod 发行者来获取它。由此,它将提出请求并为我们安装证书到机密信息之中!

大功告成! 让我们尝试一下。

它现在具有了加密 TLS 所有优点!恭喜你!


via: https://opensource.com/article/20/3/ssl-letsencrypt-k3s

作者:Lee Carpenter 选题:lujun9972 译者:wxy 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

将流量引入 Kubernetes 树莓派集群的分步指南。

在本文中,我们将部署几个简单的网站,并学习如何使用 Traefik 将来自外部世界的流量引入到我们的集群中。之后,我们还将学习如何删除 Kubernetes 资源。让我们开始吧!

准备

要继续阅读本文,你只需要我们在上一篇文章中构建的 k3s 树莓派集群。由于你的集群将从网络上拉取镜像,因此该集群需要能够访问互联网。

出于解释目的,本文将显示一些配置文件和示例 HTML 文件。所有示例文件都可以在此处下载。

部署一个简单的网站

之前,我们使用 kubectl 进行了直接部署。但是,这不是典型的部署方法。一般情况都会使用 YAML 配置文件,这也是我们要在本文中使用的配置文件。我们将从顶部开始,并以自顶向下的方式创建该配置文件。

部署配置

首先是部署配置。配置如下所示,并在下面进行说明。我通常以 Kubernetes 文档中的示例为起点,然后根据需要对其进行修改。例如,下面的配置是复制了部署文档中的示例后修改的。

创建一个文件 mysite.yaml,其内容如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysite-nginx
  labels:
    app: mysite-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysite-nginx
  template:
    metadata:
      labels:
        app: mysite-nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80

其中大部分是样板。重要的部分,我们会将该部署命名为 mysite-nginx,并为其加上同名的 app 标签。我们指定了一个 副本 replica ,这意味着将只创建一个 Pod。我们还指定了一个容器,我们将其命名为 nginx。我们将 镜像 image 指定为 nginx。这意味着在部署时,k3s 将从 DockerHub 下载 nginx 镜像并从中创建一个 Pod。最后,我们指定了 容器端口 containerPort 80,这只意味着在容器内部 Pod 会监听 80 端口。

我在上面强调了“在容器内部”,因为这是一个重要的区别。由于我们是按容器配置的,因此只能在容器内部访问它,并且进一步将其限制为内部网络。这对于允许多个容器在同一容器端口上监听所是必要的。换句话说,通过这种配置,其他一些 Pod 也可以在其容器端口 80 上侦听,并且不会与此容器冲突。为了提供对该 Pod 的正式访问权限,我们需要一个 服务 service 配置。

服务配置

在 Kubernetes 中, 服务 service 是一种抽象。它提供了一种访问 Pod 或 Pod 集合的方法。当连接到服务时,服务会路由到单个 Pod,或者如果定义了多个 Pod 副本,会通过负载均衡路由到多个 Pod。

可以在同一配置文件中指定该服务,这就是我们将在此处要做的。用 --- 分隔配置区域,将以下内容添加到 mysite.yaml 中:

---
apiVersion: v1
kind: Service
metadata:
  name: mysite-nginx-service
spec:
  selector:
    app: mysite-nginx
  ports:
    - protocol: TCP
      port: 80

在此配置中,我们将服务命名为 mysite-nginx-service。我们提供了一个 选择器 selector app: mysite-nginx。这是服务选择其路由到的应用程序容器的方式。请记住,我们为容器提供了 app 标签:mysite-nginx 。这就是服务用来查找我们的容器的方式。最后,我们指定服务协议为 TCP,在端口 80 上监听。

入口配置

入口 Ingress 配置指定了如何将流量从集群外部传递到集群内部的服务。请记住,k3s 预先配置了 Traefik 作为入口控制器。因此,我们将编写特定于 Traefik 的入口配置。将以下内容添加到 mysite.yaml 中(不要忘了用 --- 分隔):

---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: mysite-nginx-ingress
  annotations:
    kubernetes.io/ingress.class: "traefik"
spec:
  rules:
  - http:
      paths:
      - path: /
        backend:
          serviceName: mysite-nginx-service
          servicePort: 80

在此配置中,我们将入口记录命名为 mysite-nginx-ingress。我们告诉 Kubernetes,我们希望 traefik 成为我们的入口控制器,再加上 kubernetes.io/ingress.class 的注解。

规则 rules 部分中,我们基本上是说,当 http 流量进入时,并且 path 匹配 /(或其下的任何内容),将其路由到由 serviceName mysite-nginx-service 指定的 后端 backend 服务中,并将其路由到 servicePort 80。这会将传入的 HTTP 流量连接到我们之前定义的服务。

需要部署的东西

就配置而言,就是这样了。如果我们现在部署,我们将获得默认的 nginx 页面,但这不是我们想要的。让我们创建一些简单但可自定义的部署方式。创建具有以下内容的文件 index.html

<html>
<head><title>K3S!</title>
  <style>
    html {
      font-size: 62.5%;
    }
    body {
      font-family: sans-serif;
      background-color: midnightblue;
      color: white;
      display: flex;
      flex-direction: column;
      justify-content: center;
      height: 100vh;
    }
    div {
      text-align: center;
      font-size: 8rem;
      text-shadow: 3px 3px 4px dimgrey;
    }
  </style>
</head>
<body>
  <div>Hello from K3S!</div>
</body>
</html>

我们尚未介绍 Kubernetes 中的存储机制,因此在这里我们偷懒一下,仅将该文件存储在 Kubernetes 配置映射中。这不是我们推荐的部署网站的方式,但对于我们的目的来说是可行的。运行以下命令:

kubectl create configmap mysite-html --from-file index.html

该命令从本地文件 index.html 创建名为 mysite-html 配置映射 configmap 资源。这实际上是在 Kubernetes 资源中存储一个文件(或一组文件),我们可以在配置中调出该文件。它通常用于存储配置文件(因此而得名),我们在这里稍加滥用。在以后的文章中,我们将讨论 Kubernetes 中适当的存储解决方案。

创建配置映射后,让我们将其挂载在我们的 nginx 容器中。我们分两个步骤进行。首先,我们需要指定一个 volume 来调出配置映射。然后我们需要将该卷挂载到 nginx 容器中。通过在 mysite.yaml 中的 container 后面的 spec 标签下添加以下内容来完成第一步:

      volumes:
      - name: html-volume
        configMap:
          name: mysite-html

这告诉 Kubernetes 我们要定义一个名为 html-volume 的卷,并且该卷应包含名为 html-volume(我们在上一步中创建的)的配置映射的内容。

接下来,在 nginx 容器规范中的 端口 ports 下方,添加以下内容:

        volumeMounts:
        - name: html-volume
          mountPath: /usr/share/nginx/html

这告诉 Kubernetes,对于 nginx 容器,我们想在容器中的 /usr/share/nginx/html 路径上挂载名为 html-volume 的卷。 为什么要使用 /usr/share/nginx/html?那个位置就是 nginx 镜像提供 HTML 服务的地方。通过在该路径上挂载卷,我们用该卷内容替换了默认内容。

作为参考,配置文件的 deployment 部分现在应如下所示:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysite-nginx
  labels:
    app: mysite-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysite-nginx
  template:
    metadata:
      labels:
        app: mysite-nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - name: html-volume
          mountPath: /usr/share/nginx/html
      volumes:
      - name: html-volume
        configMap:
          name: mysite-html

部署它!

现在我们准备部署! 我们可以这样做:

kubectl apply -f mysite.yaml

你应该看到类似于以下内容:

deployment.apps/mysite-nginx created
service/mysite-nginx-service created
ingress.networking.k8s.io/mysite-nginx-ingress created

这意味着 Kubernetes 为我们指定的三个配置分别创建了资源。使用以下方法检查 Pod 的状态:

kubectl get pods

如果看到状态为 ContainerCreating,请给它一些时间并再次运行 kubectl get pods。通常,第一次会花一些时间,因为 k3s 必须下载 nginx 镜像来创建 Pod。一段时间后,你应该看到 Running 的状态。

尝试一下!

Pod 运行之后,就该尝试了。打开浏览器,然后在地址栏中输入 kmaster

恭喜你!你已经在 k3s 集群上部署了一个网站!

另一个

因此,现在我们有了一个运行单个网站的整个 k3s 集群。但是我们可以有更多的网站!如果我们要在同一集群中提供另一个网站怎么办?让我们看看如何做到这一点。

同样,我们需要部署一些东西。碰巧我的狗有一条她想让全世界都知道的信息,她想了好久了。因此,我专门为她制作了一些 HTML(可从示例 zip 文件中获得)。同样,我们将使用配置映射的技巧来托管这些 HTML。这次我们将把整个目录(html 目录)放到配置映射中,但是调用是相同的。

kubectl create configmap mydog-html --from-file html

现在,我们需要为此站点创建一个配置文件。它几乎与用于 mysite.yaml 的完全相同,因此首先将 mysite.yaml 复制为 mydog.yaml。现在将 mydog.yaml 修改为:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mydog-nginx
  labels:
    app: mydog-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mydog-nginx
  template:
    metadata:
      labels:
        app: mydog-nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - name: html-volume
          mountPath: /usr/share/nginx/html
      volumes:
      - name: html-volume
        configMap:
          name: mydog-html
---
apiVersion: v1
kind: Service
metadata:
  name: mydog-nginx-service
spec:
  selector:
    app: mydog-nginx
  ports:
    - protocol: TCP
      port: 80
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: mydog-nginx-ingress
  annotations:
    kubernetes.io/ingress.class: "traefik"
    traefik.frontend.rule.type: PathPrefixStrip
spec:
  rules:
  - http:
      paths:
      - path: /mydog
        backend:
          serviceName: mydog-nginx-service
          servicePort: 80

我们只需进行搜索并将 mysite 替换为 mydog即可完成大多数修改。其他两个修改在入口部分中。我们将 path 更改为 /mydog,并添加了一个注解 traefik.frontend.rule.type: PathPrefixStrip

/mydog 路径的规范指示 Traefik 将以 /mydog 路径开头的所有传入请求路由到 mydog-nginx-service。任何其他路径将继续路由到 mysite-nginx-service

新的注解 PathPrefixStrip 告诉 Traefik 在将请求发送到 mydog-nginx-service 之前先去除前缀 /mydog。我们这样做是因为 mydog-nginx 应用程序不需要前缀。这意味着我们可以简单地通过更改入口记录中的前缀来更改挂载的服务的位置。

现在我们可以像以前一样进行部署:

kubectl apply -f mydog.yaml

现在,我的狗的消息应该可以在 http://kmaster/mydog/ 上找到。

呼!消息发出去了!也许今晚我们都可以睡一觉。

因此,现在,我们有了一个 k3s 集群,该集群托管了两个网站,Traefik 根据路径名决定将请求传递给哪个服务!但是,不仅限于基于路径的路由,我们也可以使用基于主机名的路由,我们将在以后的文章中进行探讨。

另外,我们刚刚托管的网站是标准的未加密 HTML 网站,而如今的所有内容都使用 SSL/TLS 加密。在我们的下一篇文章中,我们将为 k3s 集群添加支持以托管 SSL/TLS HTTPS 站点!

清理

在开始之前,由于本文主要涉及的是示例站点,因此我想向你展示如何删除内容,以防万一你不希望将这些示例丢在集群中。

对于大多数配置,只需使用与部署时使用的相同配置文件运行 delete 命令即可撤消配置。因此,让我们同时清理 mysitemydog

kubectl delete -f mysite.yaml
kubectl delete -f mydog.yaml

由于我们是手动创建配置映射的,因此我们也需要手动删除它们。

kubectl delete configmap mysite-html
kubectl delete configmap mydog-html

现在,如果我们执行 kubectl get pods,我们应该看到我们的 nginx Pod 不存在了。

$ kubectl get pods
No resources found in default namespace.

一切都清理了。

请在下面的评论中告诉我你对这个项目有什么想法。


via: https://opensource.com/article/20/3/kubernetes-traefik

作者:Lee Carpenter 选题:lujun9972 译者:wxy 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

跟随接下来的介绍,自己搭建一个三节点的 Kubernetes 集群。

我对在树莓派上搭建 Kubernetes 集群已经感兴趣很长时间了,只要照着网上的教程,我可以在由三个树莓派组成的集群中搭建一套 Kubernetes 并正常运行。但在这种情况下,主节点上的内存和 CPU 资源捉襟见肘,执行 Kubernetes 任务的时候往往性能不佳,想要升级 Kubernetes 就更不可能了。

这个时候,我非常激动地发现了 K3s 这个项目。K3s 被誉为在可用于资源受限环境下的轻量级 Kubernetes,它还针对 ARM 处理器做出了优化,这让 Kubernetes 集群可以在树莓派上运行得更好。在下文中,我们将会使用 K3s 来创建一个 Kubernetes 集群。

准备

要按照本文介绍的方式创建 Kubernetes 集群,首先需要准备:

  • 至少一个树莓派(包括 SD 卡和电源)
  • 网线
  • 将所有树莓派连接到一起的交换机或路由器

我们会通过在线安装的方式安装 K3s,因此还需要可以连接到互联网。

集群概览

在这个集群里,我们会使用三个树莓派。其中一个树莓派作为主节点,我们将它命名为 kmaster,并为其分配一个静态 IP 192.168.0.50(注:假设使用的私有网段是 192.168.0.0/24),而另外两个树莓派作为工作节点,分别命名为 knode1knode2,也分别分配 192.168.0.51192.168.0.52 两个 IP 地址。

当然,如果你实际的网络布局和上面不同,只要将文中所提及到的 IP 替换成你实际可用的 IP 就可以了。

为了不需要通过 IP 来引用某一个节点,我们将每个节点的主机名记录到 PC 的 /etc/hosts 文件当中:

echo -e "192.168.0.50\tkmaster" | sudo tee -a /etc/hosts
echo -e "192.168.0.51\tknode1" | sudo tee -a /etc/hosts
echo -e "192.168.0.52\tknode2" | sudo tee -a /etc/hosts

部署主节点

我们首先部署主节点。最开始的步骤当然是使用镜像安装最新的 Raspbian,这个步骤可以参考我的另一篇文章,在这里就不展开介绍了。在安装完成之后,启动 SSH 服务,将主机名设置为 kmaster,然后分配静态 IP 192.168.0.50

在主节点上安装 Raspbian 完成后,启动树莓派并通过 ssh 连接上去:

ssh pi@kmaster

在主节点上执行以下命令安装 K3s:

curl -sfL https://get.k3s.io | sh -

等到命令跑完以后,一个单节点集群就已经运行起来了。让我们检查一下,还在这个树莓派上执行:

sudo kubectl get nodes

就会看到这样的输出:

NAME     STATUS   ROLES    AGE    VERSION
kmaster  Ready    master   2m13s  v1.14.3-k3s.1

获取 连接令牌 join token

之后我们需要部署工作节点。在工作节点上安装 K3s 的时候,会需要用到连接令牌,它放置在主节点的文件系统上。首先把连接令牌保存出来以便后续使用:

sudo cat /var/lib/rancher/k3s/server/node-token

部署工作节点

通过 SD 卡在每个作为工作节点的树莓派上安装 Raspbian。在这里,我们把其中一个树莓派的主机名设置为 knode1,为其分配 IP 地址 192.168.0.51,另一个树莓派的主机名设置为 knode2,分配 IP 地址 192.168.0.52。接下来就可以安装 K3s 了。

启动主机名为 knode1 的树莓派,通过 ssh 连接上去:

ssh pi@knode1

在这个树莓派上,安装 K3s 的过程和之前差不多,但需要另外加上一些参数,表示它是一个工作节点,需要连接到一个已有的集群上:

curl -sfL http://get.k3s.io | K3S_URL=https://192.168.0.50:6443 \
K3S_TOKEN=刚才保存下来的连接令牌 sh -

K3S_TOKEN 的值需要替换成刚才保存下来的实际的连接令牌。完成之后,在主机名为 knode2 的树莓派上重复这个安装过程。

通过 PC 访问集群

现在如果我们想要查看或者更改集群,都必须 ssh 到集群的主节点才能使用 kubectl,这是比较麻烦的。因此我们会将 kubectl 放到 PC 上使用。首先,在主节点上获取一些必要的配置信息,sshkmaster 上执行:

sudo cat /etc/rancher/k3s/k3s.yaml

复制上面命令的输出,然后在你的 PC 上创建一个目录用来放置配置文件:

mkdir ~/.kube

将复制好的内容写入到 ~/.kube/config 文件中,然后编辑该文件,将

server: https://localhost:6443

改为

server: https://kmaster:6443

出于安全考虑,只对自己保留这个配置文件的读写权限:

chmod 600 ~/.kube/config

如果 PC 上还没有安装 kubectl 的话,就可以开始安装了。Kubernetes 官方网站上有各种平台安装 kubectl方法说明,我使用的是 Ubuntu 的衍生版 Linux Mint,所以我的安装方法是这样的:

sudo apt update && sudo apt install -y apt-transport-https
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee -a /etc/apt/sources.list.d/kubernetes.list
sudo apt update && sudo apt install kubectl

上面几个命令的作用是添加了一个包含 Kubernetes 的 Debian 软件库,获取 GPG 密钥以确保安全,然后更新软件包列表并安装 kubectl。如果 kubectl 有更新,我们将会通过 标准软件更新机制 standard software update mechanism 收到通知。

现在在 PC 上就可以查看 Kubernetes 集群了:

kubectl get nodes

输出大概会是这样:

NAME     STATUS  ROLES   AGE   VERSION
kmaster  Ready   master  12m   v1.14.3-k3s.1
knode1   Ready   worker  103s  v1.14.3-k3s.1
knode1   Ready   worker  103s  v1.14.3-k3s.1

至此,我们已经搭建了一个三节点的 Kubernetes 集群。

K3s 的彩蛋

如果执行 kubectl get pods --all-namespaces,就会看到其它服务的一些 Pod,比如 Traefik。Traefik 在这里起到是反向代理和负载均衡器的作用,它可以让流量从单个入口进入集群后引导到集群中的各个服务。Kubernetes 支持这种机制,但 Kubernetes 本身不提供这个功能,因此 Traefik 是一个不错的选择,K3s 安装后立即可用的优点也得益于此。

在后续的文章中,我们会继续探讨 Traefik 在 Kubernetes ingress 中的应用,以及在集群中部署其它组件。敬请关注。


via: https://opensource.com/article/20/3/kubernetes-raspberry-pi-k3s

作者:Lee Carpenter 选题:lujun9972 译者:HankChow 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

Fedora IoT 是一个即将发布的、面向物联网的 Fedora 版本。去年 Fedora Magazine 的《如何使用 Fedora IoT 点亮 LED 灯》一文第一次介绍了它。从那以后,它与 Fedora Silverblue 一起不断改进,以提供针对面向容器的工作流的不可变基础操作系统。

Kubernetes 是一个颇受欢迎的容器编排系统。它可能最常用在那些能够处理巨大负载的强劲硬件上。不过,它也能在像树莓派 3 这样轻量级的设备上运行。让我们继续阅读,来了解如何运行它。

为什么用 Kubernetes?

虽然 Kubernetes 在云计算领域风靡一时,但让它在小型单板机上运行可能并不是常见的。不过,我们有非常明确的理由来做这件事。首先,这是一个不需要昂贵硬件就可以学习并熟悉 Kubernetes 的好方法;其次,由于它的流行性,市面上有大量应用进行了预先打包,以用于在 Kubernetes 集群中运行。更不用说,当你遇到问题时,会有大规模的社区用户为你提供帮助。

最后但同样重要的是,即使是在家庭实验室这样的小规模环境中,容器编排也确实能够使事情变得更加简单。虽然在学习曲线方面,这一点并不明显,但这些技能在你将来与任何集群打交道的时候都会有帮助。不管你面对的是一个单节点树莓派集群,还是一个大规模的机器学习场,它们的操作方式都是类似的。

K3s - 轻量级的 Kubernetes

一个“正常”安装的 Kubernetes(如果有这么一说的话)对于物联网来说有点沉重。K8s 的推荐内存配置,是每台机器 2GB!不过,我们也有一些替代品,其中一个新人是 k3s —— 一个轻量级的 Kubernetes 发行版。

K3s 非常特殊,因为它将 etcd 替换成了 SQLite 以满足键值存储需求。还有一点,在于整个 k3s 将使用一个二进制文件分发,而不是每个组件一个。这减少了内存占用并简化了安装过程。基于上述原因,我们只需要 512MB 内存即可运行 k3s,极度适合小型单板电脑!

你需要的东西

  1. Fedora IoT 运行在虚拟机或实体设备中运行的。在这里可以看到优秀的入门指南。一台机器就足够了,不过两台可以用来测试向集群添加更多节点。
  2. 配置防火墙,允许 6443 和 8372 端口的通信。或者,你也可以简单地运行 systemctl stop firewalld 来为这次实验关闭防火墙。

安装 k3s

安装 k3s 非常简单。直接运行安装脚本:

curl -sfL https://get.k3s.io | sh -

它会下载、安装并启动 k3s。安装完成后,运行以下命令来从服务器获取节点列表:

kubectl get nodes

需要注意的是,有几个选项可以通过环境变量传递给安装脚本。这些选项可以在文档中找到。当然,你也完全可以直接下载二进制文件来手动安装 k3s。

对于实验和学习来说,这样已经很棒了,不过单节点的集群也不能算一个集群。幸运的是,添加另一个节点并不比设置第一个节点要难。只需要向安装脚本传递两个环境变量,它就可以找到第一个节点,而不用运行 k3s 的服务器部分。

curl -sfL https://get.k3s.io | K3S_URL=https://example-url:6443 \
  K3S_TOKEN=XXX sh -

上面的 example-url 应被替换为第一个节点的 IP 地址,或一个完全限定域名。在该节点中,(用 XXX 表示的)令牌可以在 /var/lib/rancher/k3s/server/node-token 文件中找到。

部署一些容器

现在我们有了一个 Kubernetes 集群,我们可以真正做些什么呢?让我们从部署一个简单的 Web 服务器开始吧。

kubectl create deployment my-server --image nginx

这会从名为 nginx 的容器镜像中创建出一个名叫 my-server部署(默认使用 docker hub 注册中心,以及 latest 标签)。

kubectl get pods

为了访问到 pod 中运行的 nginx 服务器,首先通过一个 服务 来暴露该部署。以下命令将创建一个与该部署同名的服务。

kubectl expose deployment my-server --port 80

服务将作为一种负载均衡器和 Pod 的 DNS 记录来工作。比如,当运行第二个 Pod 时,我们只需指定 my-server(服务名称)就可以通过 curl 访问 nginx 服务器。有关如何操作,可以看下面的实例。

# 启动一个 pod,在里面以交互方式运行 bash
kubectl run debug --generator=run-pod/v1 --image=fedora -it -- bash
# 等待 bash 提示符出现
curl my-server
# 你可以看到“Welcome to nginx!”的输出页面

Ingress 控制器及外部 IP

默认状态下,一个服务只能获得一个 ClusterIP(只能从集群内部访问),但你也可以通过把它的类型设置为 LoadBalancer 为该服务申请一个外部 IP。不过,并非所有应用都需要自己的 IP 地址。相反,通常可以通过基于 Host 请求头部或请求路径进行路由,从而使多个服务共享一个 IP 地址。你可以在 Kubernetes 使用 Ingress 完成此操作,而这也是我们要做的。Ingress 也提供了额外的功能,比如无需配置应用即可对流量进行 TLS 加密。

Kubernetes 需要 Ingress 控制器来使 Ingress 资源工作,k3s 包含 Traefik 正是出于此目的。它还包含了一个简单的服务负载均衡器,可以为集群中的服务提供外部 IP。这篇文档描述了这种服务:

k3s 包含一个使用可用主机端口的基础服务负载均衡器。比如,如果你尝试创建一个监听 80 端口的负载均衡器,它会尝试在集群中寻找一个 80 端口空闲的节点。如果没有可用端口,那么负载均衡器将保持在 Pending 状态。

k3s README

Ingress 控制器已经通过这个负载均衡器暴露在外。你可以使用以下命令找到它正在使用的 IP 地址。

$ kubectl get svc --all-namespaces
NAMESPACE     NAME         TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
 default       kubernetes   ClusterIP      10.43.0.1               443/TCP                      33d
 default       my-server    ClusterIP      10.43.174.38            80/TCP                       30m
 kube-system   kube-dns     ClusterIP      10.43.0.10              53/UDP,53/TCP,9153/TCP       33d
 kube-system   traefik      LoadBalancer   10.43.145.104   10.0.0.8      80:31596/TCP,443:31539/TCP   33d

找到名为 traefik 的服务。在上面的例子中,我们感兴趣的 IP 是 10.0.0.8。

路由传入的请求

让我们创建一个 Ingress,使它通过基于 Host 头部的路由规则将请求路由至我们的服务器。这个例子中我们使用 xip.io 来避免必要的 DNS 记录配置工作。它的工作原理是将 IP 地址作为子域包含,以使用 10.0.0.8.xip.io 的任何子域来达到 IP 10.0.0.8。换句话说,my-server.10.0.0.8.xip.io 被用于访问集群中的 Ingress 控制器。你现在就可以尝试(使用你自己的 IP,而不是 10.0.0.8)。如果没有 Ingress,你应该会访问到“默认后端”,只是一个写着“404 page not found”的页面。

我们可以使用以下 Ingress 让 Ingress 控制器将请求路由到我们的 Web 服务器的服务。

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-server
spec:
  rules:
    - host: my-server.10.0.0.8.xip.io
      http:
        paths:
          - path: /
            backend:
              serviceName: my-server
              servicePort: 80

将以上片段保存到 my-ingress.yaml 文件中,然后运行以下命令将其加入集群:

kubectl apply -f my-ingress.yaml

你现在应该能够在你选择的完全限定域名中访问到 nginx 的默认欢迎页面了。在我的例子中,它是 my-server.10.0.0.8.xip.io。Ingress 控制器会通过 Ingress 中包含的信息来路由请求。对 my-server.10.0.0.8.xip.io 的请求将被路由到 Ingress 中定义为 backend 的服务和端口(在本例中为 my-server80)。

那么,物联网呢?

想象如下场景:你的家或农场周围有很多的设备。它是一个具有各种硬件功能、传感器和执行器的物联网设备的异构集合。也许某些设备拥有摄像头、天气或光线传感器。其它设备可能会被连接起来,用来控制通风、灯光、百叶窗或闪烁的 LED。

这种情况下,你想从所有传感器中收集数据,在最终使用它来制定决策和控制执行器之前,也可能会对其进行处理和分析。除此之外,你可能还想配置一个仪表盘来可视化那些正在发生的事情。那么 Kubernetes 如何帮助我们来管理这样的事情呢?我们怎么保证 Pod 在合适的设备上运行?

简单的答案就是“标签”。你可以根据功能来标记节点,如下所示:

kubectl label nodes <node-name> <label-key>=<label-value>
# 举例
kubectl label nodes node2 camera=available

一旦它们被打上标签,我们就可以轻松地使用 nodeSelector 为你的工作负载选择合适的节点。拼图的最后一块:如果你想在所有合适的节点上运行 Pod,那应该使用 DaemonSet 而不是部署。换句话说,应为每个使用唯一传感器的数据收集应用程序创建一个 DaemonSet,并使用 nodeSelector 确保它们仅在具有适当硬件的节点上运行。

服务发现功能允许 Pod 通过服务名称来寻找彼此,这项功能使得这类分布式系统的管理工作变得易如反掌。你不需要为应用配置 IP 地址或自定义端口,也不需要知道它们。相反,它们可以通过集群中的命名服务轻松找到彼此。

充分利用空闲资源

随着集群的启动并运行,收集数据并控制灯光和气候,可能使你觉得你已经把它完成了。不过,集群中还有大量的计算资源可以用于其它项目。这才是 Kubernetes 真正出彩的地方。

你不必担心这些资源的确切位置,或者去计算是否有足够的内存来容纳额外的应用程序。这正是编排系统所解决的问题!你可以轻松地在集群中部署更多的应用,让 Kubernetes 来找出适合运行它们的位置(或是否适合运行它们)。

为什么不运行一个你自己的 NextCloud 实例呢?或者运行 gitea?你还可以为你所有的物联网容器设置一套 CI/CD 流水线。毕竟,如果你可以在集群中进行本地构建,为什么还要在主计算机上构建并交叉编译它们呢?

这里的要点是,Kubernetes 可以更容易地利用那些你可能浪费掉的“隐藏”资源。Kubernetes 根据可用资源和容错处理规则来调度 Pod,因此你也无需手动完成这些工作。但是,为了帮助 Kubernetes 做出合理的决定,你绝对应该为你的工作负载添加资源请求配置。

总结

尽管 Kuberenetes 或一般的容器编排平台通常不会与物联网相关联,但在管理分布式系统时,使用一个编排系统肯定是有意义的。你不仅可以使用统一的方式来处理多样化和异构的设备,还可以简化它们的通信方式。此外,Kubernetes 还可以更好地对闲置资源加以利用。

容器技术使构建“随处运行”应用的想法成为可能。现在,Kubernetes 可以更轻松地来负责“随处”的部分。作为构建一切的不可变基础,我们使用 Fedora IoT。


via: https://fedoramagazine.org/kubernetes-on-fedora-iot-with-k3s/

作者:Lennart Jern 选题:lujun9972 译者:StdioA 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出