资料内容:
2.2.1 How declarative configuration works
As we saw in the previous exercise, declarative configuration management is powered
by the kubectl apply command. In contrast with imperative kubectl commands, like
scale and annotate, the kubectl apply command has one parameter, the path to
the file containing the resource manifest:
kubectl apply -f ./resource.yaml
The command is responsible for figuring out which changes should be applied to the
matching resource in the Kubernetes cluster and update the resource using the
Kubernetes API. It is a critical feature that makes Kubernetes a perfect fit for GitOps.
Let’s learn more about the logic behind kubectl apply and understand what it can
and cannot do. To understand which problems kubectl apply is solving, let’s go
through different scenarios using the Deployment resource we created earlier.
The simplest scenario is when the matching resource does not exist in the Kuber
netes cluster. In this case, kubectl creates a new resource using the manifest stored in
the specified file.
If the matching resource exists, why doesn’t kubectl replace it? The answer is obvi
ous if you look at the complete manifest resource using the kubectl get command.
Following is a partial listing of the Deployment resource that was created in the exam
ple. Some parts of the manifest have been omitted for clarity (indicated with ellipses):
$ kubectl get deployment nginx-declarative -o=yaml
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "1"
environment: prod
kubectl.kubernetes.io/last-applied-configuration: |
{ ... }
organization: marketing35
Declarative vs. imperative object management
creationTimestamp: "2019-10-15T00:57:44Z"
generation: 2
name: nginx-declarative
Namespace: default
resourceVersion: "349411"
selfLink: /apis/apps/v1/Namespaces/default/deployments/nginx-declarative
uid: d41cf3dc-a3e8-40dd-bc81-76afd4a032b1
spec:
progressDeadlineSeconds: 600
replicas: 3
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx-declarative
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
...
status:
...
As you may have noticed, a live resource manifest includes all the fields specified in
the file plus dozens of new fields such as additional metadata, the status field, and
other fields in the resource spec. All these additional fields are populated by the
Deployment controller and contain important information about the resource’s run
ning state. The controller populates information about resource state in the status
field and applies default values of all unspecified optional fields, such as revision
HistoryLimit and strategy. To preserve this information, kubectl apply
merges the manifest from the specified file and the live resource manifest. As a result,
the command updates only fields specified in the file, keeping everything else
untouched. So if we decide to scale down the deployment and change the replicas
field to 1, then kubectl changes only that field in the live resource and saves it back to
Kubernetes using an update API.
In real life, we don’t want to control all possible fields that influence resource
behavior in a declarative way. It makes sense to leave some room for imperativeness
and skip fields that should be changed dynamically. The replicas field of the
Deployment resource is a perfect example. Instead of hardcoding the number of rep
licas you want to use, the Horizontal Pod Autoscaler can be used to dynamically scale
up or scale down your application based on load.