我们以一个go语言编写的程序代码为例,创建一个简单的Web服务,当该服务接收到HTTP GET请求时会根据环境变量TARGET传递的内容向response输出Hello $TATGET! 内容。
1. 创建一个文件名为helloworld.go的文件。程序源码如下:
package main
import (
"fmt"
"log"
"net/http"
"os"
)
func handler(w http.ResponseWriter, r *http.Request) {
log.Print("helloworld: received a request")
target := os.Getenv("TARGET")
if target == "" {
target = "World"
}
fmt.Fprintf(w, "Hello %s!\n", target)
}
func main() {
log.Print("helloworld: starting server...")
http.HandleFunc("/", handler)
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
log.Printf("helloworld: listening on port %s", port)
log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil))
}
使用下面内容的Dockerfile构建源码并生成容器:
# Use the official Golang image to create a build artifact.
# This is based on Debian and sets the GOPATH to /go.
# https://hub.docker.com/_/golang
FROM golang:1.13 as builder
# Create and change to the app directory.
WORKDIR /app
# Retrieve application dependencies using go modules.
# Allows container builds to reuse downloaded dependencies.
COPY go.* ./
RUN go mod download
# Copy local code to the container image.
COPY . ./
# Build the binary.
# -mod=readonly ensures immutable go.mod and go.sum in container builds.
RUN CGO_ENABLED=0 GOOS=linux go build -mod=readonly -v -o server
# Use the official Alpine image for a lean production container.
# https://hub.docker.com/_/alpine
# https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
FROM alpine:3
RUN apk add --no-cache ca-certificates
# Copy the binary to the production image from the builder stage.
COPY --from=builder /app/server /server
# Run the web service on container startup.
CMD ["/server"]
# 在本地主机构建容器。{username}替换为你自己在dockerhub的用户名。
docker build -t {username}/helloworld-go .
# 将容器Push到Docker容器镜像仓库。{username}替换为你自己在dockerhub的用户名。
docker push {username}/helloworld-go
部署Knative Service
Knative Service和其他Kubernetes资源类似,可以通过一个YAML文件进行定义和部署。接下来我们使用上一步构建的容器来部署Knative Service服务。service.yaml配置文件如下:
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: helloworld-go # Service名称
namespace: default
spec:
template:
metadata:
name: helloworld-go-v1 # Knative Revision名称,如果未设置系统将会自动生成。
spec:
containers:
- image: {username}/helloworld-go
env:
- name: TARGET
value: "Go Sample v1"
livenessProbe:
httpGet:
path: /
readinessProbe:
httpGet:
path: /
运行下面的命令部署helloworld-go Knative Service:
# kubectl apply -f service.yaml
在这个YAML配置文件中,Knative Service的kind的值是Service,为了避免与Kubernetes内置的service混淆,apiVersion的值需要设置为serving.knative.dev/v1。
配置文件中的spec区块与Kubernetes PodSpec的定义几乎完全一样,只是删除了以下属性:
• InitContainers
• RestartPolicy
• TerminationGracePeriodSeconds
• ActiveDeadlineSeconds
• DNSPolicy
• NodeSelector
• AutomountServiceAccountToken
• NodeName
• HostNetwork
• HostPID
• HostIPC
• ShareProcessNamespace
• SecurityContext
• Hostname
• Subdomain
• Affinity
• SchedulerName
• Tolerations
• HostAliases
• PriorityClassName
• Priority
• DNSConfig
• ReadinessGates
• RuntimeClassName
spec.template.metadata.name定义了Knative Revision的名称,这个名称是可选的,如果被省略,Revision的名称会自动生成。
Knative Service的liveness探针与标准Kubernetes探针有微小区别。Knative Service探针定义中没有port属性定义。Knative Serving控制器在service部署阶段能够自动确定port值。readiness探针也遵循同样的规则。
检查部署结果并验证服务:
# kubectl get ksvc helloworld-go
NAME URL LATESTCREATED LATESTREADY READY REASON
helloworld-go http://helloworld-go.default.example.com helloworld-go-v1 helloworld-go-v1 True
通过curl命令访问helloworld-go服务:
##获取集群任一节点的IP地址和nodePort端口
# IP_ADDRESS="$(kubectl get nodes -o 'jsonpath={.items[0].status.addresses[0].address}'):$(kubectl get svc istio-ingressgateway --namespace istio-system --output 'jsonpath={.spec.ports[?(@.port==80)].nodePort}')"
# curl -H "Host:helloworld-go.default.example.com" http://$IP_ADDRESS
Hello Go Sample v1!
上面的脚本中为了获取可以访问到helloworld-go服务的ip地址以端口号,我们选取了集群任一节点的ip地址,istio-ingressgateway服务的nodePort端口号。使用带有Service URL的主机名的头信息(例如Host:helloworld-go.default.example.com)即可访问helloworld-go服务了。
当curl访问到服务后,knative Serving自动创建了一个pod副本提供服务,当一段时间没有访问服务后,pod副本将会被销毁。我们可以通过watch kubectl get pods 来监控pod的生命周期。
本文摘编于机械工业出版社出版的图书《Knative实战:基于Kubernetes的无服务器架构实践》。
关于作者:
李志伟 某网云原生实验室负责人,容器云领域专家。在Kubernetes、Istio、Serverless、DevOps工具等领域有深入的研究和实践。热心于云原生技术的应用与推广,曾荣获“K8sMeetup中国社区”最受欢迎讲师奖项。
游杨 某网云原生实验室高级运维开发工程师。先后参与Kubernetes和Knative项目的落地与实施工作,拥有丰富的容器平台实践经验,聚焦于Kubernetes、Serverless、CI/CD技术领域。
本书的读者对象:
对Serverless技术感兴趣的读者。
想要将Knative引入当前技术栈的架构师。
想要采用Serverless技术的应用开发者。
想要自己维护Knative Serverless平台的运维开发人员。
扫码关注【图书小编辑】视频号
每天来听华章哥讲书
资讯 | DB-Engines 4月数据库排名:Redis有望甩掉“千年老七”?
书单 | 8本书助你零基础转行数据分析岗
干货 | 抛开数学,一文了解推荐系统框架及原理
收藏 | 终于有人将金融风险管理讲明白了
赠书 | 【第50期】10本金融科技好书为你转行、升职和加薪助力
点击阅读全文购买