Improve Book introduction

This commit is contained in:
Phillip Wittrock 2019-03-21 13:29:22 -07:00
parent 4613fbed81
commit 62c7150009
24 changed files with 1538 additions and 540 deletions

View File

@ -1,96 +1,74 @@
{% panel style="info", title="TL;DR" %}
- Kubernetes runs Containerized Workloads in a cluster
- The Kubectl Book explains Kubernetes tools and workflows
- Kubectl is the Kubernetes cli
- Kubectl provides a swiss army knife of functionality for working with Kubernetes clusters
- Kubectl may be used to deploy and manage applications on Kubernetes
- Kubectl may be used for scripting and building higher-level frameworks
{% endpanel %}
# Introduction
# Kubectl
The goal of this book is to document how to configure, deploy and manage their containerized
Workloads in Kubernetes using Kubectl.
Kubectl is the Kubernetes cli version of a swiss army knife, and can do many things.
It covers the following topics:
While this Book is focused on using Kubectl to declaratively manage Applications in Kubernetes, it
also covers other Kubectl functions.
- Introduction to Kubernetes Workload APIs & Kubectl
- Declarative Configuration
- Deployment Techniques
- Printing information about Workloads
- Debugging Workloads
- Imperative Porcelain Commands
## Command Families
## Overview
Most Kubectl commands typically fall into one of a few categories:
Kubernetes is a set of APIs to run containerized Workloads in a cluster.
| Type | Used For | Description |
|----------------------------------------|----------------------------|----------------------------------------------------|
| Declarative Resource Management | Deployment and Operations (e.g. GitOps) | Declaratively manage Kubernetes Workloads using Resource Config |
| Imperative Resource Management | Development Only | Run commands to manage Kubernetes Workloads using Command Line arguments and flags |
| Printing Workload State | Debugging | Print information about Workloads |
| Interacting with Containers | Debugging | Exec, Attach, Cp, Logs |
| Cluster Management | Cluster Ops | Drain and Cordon Nodes |
Users define API objects (i.e. Resources) in files which are typically checked into source control.
They then use kubectl to Apply (i.e. create, update, delete) to update cluster state.
## Declarative Application Management
### Pods
The preferred approach for managing Resources is through
declarative files called Resource Config used with the Kubectl *Apply* command.
This command reads a local (or remote) file structure and modifies cluster state to
reflect the declared intent.
Containers are run in [*Pods*](https://kubernetes.io/docs/concepts/workloads/pods/pod-overview/) which are
scheduled to run on *Nodes* (i.e. worker machines) in a cluster.
Pods run a *single replica* of an Application and provide:
- Compute Resources (cpu, memory, disk)
- Environment Variables
- Readiness and Health Checking
- Network (IP address shared by containers in the Pod)
- Mounting Shared Configuration and Secrets
- Mounting Storage Volumes
- Initialization
{% panel style="warning", title="Multi Container Pods" %}
Multiple replicas of an Application should be created using a Workload API to manage
creation and deletion of Pod replicas using a PodTemplate.
In some cases a Pod may contain multiple Containers forming a single instance of an Application. These
containers may coordinate with one another through shared network (IP) and storage.
{% panel style="info", title="Apply" %}
Apply is the preferred mechanism for managing Resources in a Kubernetes cluster.
{% endpanel %}
### Workloads
## Printing state about Workloads
Pods are typically managed by higher level abstractions that handle concerns such as
replication, identity, persistent storage, custom scheduling, rolling updates, etc.
Users will need to view Workload state.
The most common out-of-the-box Workload APIs (manage Pods) are:
- Printing summarize state and information about Resources
- Printing complete state and information about Resources
- Printing specific fields from Resources
- Query Resources matching labels
- [Deployments](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) (Stateless Applications)
- replication + rollouts
- [StatefulSets](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/) (Stateful Applications)
- replication + rollouts + persistent storage + identity
- [Jobs](https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/) (Batch Work)
- run to completion
- [CronJobs](https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/) (Scheduled Batch Work)
- scheduled run to completion
- [DaemonSets](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/) (Per-Machine)
- per-Node scheduling
## Debugging Workloads
{% panel style="success", title="API Abstraction Layers" %}
High-level Workload APIs may manage lower-level Workload APIs instead of directly managing Pods
(e.g. Deployments manage ReplicaSets).
{% endpanel %}
### Service Discovery and Load Balancing
Service discovery and Load Balancing may be managed by a *Service* object. Services provide a single
virtual IP address and dns name load balanced to a collection of Pods matching Labels.
{% panel style="info", title="Internal vs External Services" %}
- [Services Resources](https://kubernetes.io/docs/concepts/services-networking/service/)
(L4) may expose Pods internally within a cluster or externally through an HA proxy.
- [Ingress Resources](https://kubernetes.io/docs/concepts/services-networking/ingress/) (L7)
may expose URI endpoints and route them to Services.
{% endpanel %}
### Configuration and Secrets
Shared Configuration and Secret data may be provided by ConfigMaps and Secrets. This allows
Environment Variables, Command Line Arguments and Files to be loosely injected into
the Pods and Containers that consume them.
{% panel style="info", title="ConfigMaps vs Secrets" %}
- [ConfigMaps](https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/)
are for providing non-sensitive data to Pods.
- [Secrets](https://kubernetes.io/docs/concepts/configuration/secret/)
are for providing sensitive data to Pods.
Kubectl supports debugging by providing commands for:
- Printing Container logs
- Printing cluster events
- Exec or attaching to a Container
- Copying files from Containers in the cluster to a user's filesystem
## Cluster Management
On occasion, users may need to perform operations to the Nodes of cluster. Kubectl supports
commands to drain Workloads from a Node so that it can be decommission or debugged.
## Porcelain
Users may find using Resource Config overly verbose for *Development* and prefer to work with
the cluster *imperatively* with a shell-like workflow. Kubectl offers porcelain commands for
generating and modifying Resources.
- Generating + creating Resources such as Deployments, StatefulSets, Services, ConfigMaps, etc
- Setting fields on Resources
- Editing (live) Resources in a text editor
{% panel style="danger", title="Porcelain For Dev Only" %}
Porcelain commands are time saving for experimenting with workloads in a dev cluster, but shouldn't
be used for production.
{% endpanel %}

View File

@ -1,7 +1,9 @@
## Kubectl Book
# Resource Management With Kubectl
* [Resources and Controllers](pages/kubectl_book/resources_and_controllers.md)
* [Kubectl](pages/kubectl_book/kubectl.md)
## Background Information
* [Getting Started with Kubectl](pages/kubectl_book/getting_started.md)
* [Resources + Controllers Overview](pages/kubectl_book/resources_and_controllers.md)
## App Management
@ -13,29 +15,6 @@
* [Labels and Annotations](pages/app_management/labels_and_annotations.md)
* [Field Merge Semantics](pages/app_management/field_merge_semantics.md)
## App Customization
* [Introduction](pages/app_customization/introduction.md)
* [Bases and Variations](pages/app_customization/bases_and_variants.md)
* [Customizing Pod Templates](pages/app_customization/customizing_pod_templates.md)
* [Customizing Metadata](pages/app_customization/customizing_metadata.md)
* [Customizing Arbitrary Fields](pages/app_customization/customizing_arbitrary_fields.md)
* [Config Reflection](pages/app_customization/config_reflection.md)
## App Structure
* [Introduction](pages/app_composition_and_deployment/structure_introduction.md)
* [Layout With Directories](pages/app_composition_and_deployment/structure_directories.md)
* [Layout With Branches (Experimental)](pages/app_composition_and_deployment/structure_branches.md)
* [Layout With Repositories (Experimental)](pages/app_composition_and_deployment/structure_repositories.md)
* [Multi-Tier](pages/app_composition_and_deployment/structure_multi_tier_apps.md)
## App Deployment
* [Diffing Local and Remote State](pages/app_composition_and_deployment/diffing_local_and_remote_resources.md)
* [Accessing Multiple Clusters](pages/app_composition_and_deployment/accessing_multiple_clusters.md)
* [Publishing Config as Bases (Experimental)](pages/app_composition_and_deployment/publishing_bases.md)
## Resource Printing
* [Summaries](pages/resource_printing/summaries.md)
@ -54,6 +33,28 @@
* [Port Forward to Pods](pages/container_debugging/port_forward_to_pods.md)
* [Proxying Traffic to Services](pages/container_debugging/proxying_traffic_to_services.md)
## App Customization
* [Introduction](pages/app_customization/introduction.md)
* [Bases and Variations](pages/app_customization/bases_and_variants.md)
* [Customizing Pod Templates](pages/app_customization/customizing_pod_templates.md)
* [Customizing Arbitrary Fields](pages/app_customization/customizing_arbitrary_fields.md)
* [Config Reflection](pages/app_customization/config_reflection.md)
## App Structure
* [Introduction](pages/app_composition_and_deployment/structure_introduction.md)
* [Directory Layout](pages/app_composition_and_deployment/structure_directories.md)
* [Branches Layout](pages/app_composition_and_deployment/structure_branches.md)
* [Repository Layout](pages/app_composition_and_deployment/structure_repositories.md)
* [Multi-Tier Layout](pages/app_composition_and_deployment/structure_multi_tier_apps.md)
## App Deployment
* [Diffing Local and Remote State](pages/app_composition_and_deployment/diffing_local_and_remote_resources.md)
* [Accessing Multiple Clusters](pages/app_composition_and_deployment/accessing_multiple_clusters.md)
* [Publishing Config](pages/app_composition_and_deployment/publishing_bases.md)
## Imperative Porcelain
* [Introduction](pages/imperative_porcelain/introduction.md)

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,21 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80

View File

@ -0,0 +1,6 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml

View File

@ -0,0 +1,11 @@
kind: Service
apiVersion: v1
metadata:
name: nginx
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 9376

View File

@ -43,6 +43,16 @@
"ansi-wrap": "0.1.0"
}
},
"ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
},
"ansi-styles": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
},
"ansi-wrap": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz",
@ -94,6 +104,11 @@
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
"integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
},
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
},
"bash-color": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/bash-color/-/bash-color-0.0.4.tgz",
@ -107,6 +122,48 @@
"tweetnacl": "^0.14.3"
}
},
"bindings": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
"optional": true,
"requires": {
"file-uri-to-path": "1.0.0"
}
},
"bl": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/bl/-/bl-1.0.3.tgz",
"integrity": "sha1-/FQhoo/UImA2w7OJGmaiW8ZNIm4=",
"requires": {
"readable-stream": "~2.0.5"
},
"dependencies": {
"process-nextick-args": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
"integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
},
"readable-stream": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
"integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=",
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
"isarray": "~1.0.0",
"process-nextick-args": "~1.0.6",
"string_decoder": "~0.10.x",
"util-deprecate": "~1.0.1"
}
},
"string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
}
}
},
"boolbase": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
@ -120,6 +177,15 @@
"hoek": "6.x.x"
}
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"buffer-from": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
@ -130,6 +196,18 @@
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
},
"chalk": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
"requires": {
"ansi-styles": "^2.2.1",
"escape-string-regexp": "^1.0.2",
"has-ansi": "^2.0.0",
"strip-ansi": "^3.0.0",
"supports-color": "^2.0.0"
}
},
"cheerio": {
"version": "0.20.0",
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.20.0.tgz",
@ -166,6 +244,11 @@
"resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz",
"integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ=="
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
},
"concat-stream": {
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
@ -225,6 +308,31 @@
"resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz",
"integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI="
},
"d3": {
"version": "3.5.17",
"resolved": "https://registry.npmjs.org/d3/-/d3-3.5.17.tgz",
"integrity": "sha1-vEZ0gAQ3iyGjYMn8fPUjF5B2L7g="
},
"dagre-d3-renderer": {
"version": "0.4.26",
"resolved": "https://registry.npmjs.org/dagre-d3-renderer/-/dagre-d3-renderer-0.4.26.tgz",
"integrity": "sha512-vOWj1uA4/APTrfDyfHaH/xpfXhPh9rszW+HOaEwPCeA6Afl06Lobfh7OpESuVMQW2QGuY4UQ7pte/p0WhdDs7w==",
"requires": {
"d3": "3.5.17",
"dagre-layout": "^0.8.0",
"graphlib": "^2.1.1",
"lodash": "^4.17.4"
}
},
"dagre-layout": {
"version": "0.8.8",
"resolved": "https://registry.npmjs.org/dagre-layout/-/dagre-layout-0.8.8.tgz",
"integrity": "sha512-ZNV15T9za7X+fV8Z07IZquUKugCxm5owoiPPxfEx6OJRD331nkiIaF3vSt0JEY5FkrY0KfRQxcpQ3SpXB7pLPQ==",
"requires": {
"graphlibrary": "^2.2.0",
"lodash": "^4.17.5"
}
},
"dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
@ -252,6 +360,25 @@
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
},
"dnode": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/dnode/-/dnode-1.2.2.tgz",
"integrity": "sha1-SsPP4m4pKzs5uCWK59lO3FgTLvo=",
"requires": {
"dnode-protocol": "~0.2.2",
"jsonify": "~0.0.0",
"weak": "^1.0.0"
}
},
"dnode-protocol": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/dnode-protocol/-/dnode-protocol-0.2.2.tgz",
"integrity": "sha1-URUdFvw7X4SBXuC5SXoQYdDRlJ0=",
"requires": {
"jsonify": "~0.0.0",
"traverse": "~0.6.3"
}
},
"dom-serializer": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz",
@ -302,6 +429,11 @@
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.6.tgz",
"integrity": "sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q=="
},
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
},
"escodegen": {
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.1.tgz",
@ -383,6 +515,11 @@
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
"optional": true
},
"faye-websocket": {
"version": "0.4.4",
"resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.4.4.tgz",
"integrity": "sha1-wUxbO/FNdBf/v9mQwKdJXNnzN7w="
},
"fd-slicer": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz",
@ -391,6 +528,12 @@
"pend": "~1.2.0"
}
},
"file-uri-to-path": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
"optional": true
},
"for-in": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
@ -421,6 +564,27 @@
"klaw": "^1.0.0"
}
},
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
"generate-function": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
"integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==",
"requires": {
"is-property": "^1.0.2"
}
},
"generate-object-property": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz",
"integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=",
"requires": {
"is-property": "^1.0.0"
}
},
"getpass": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
@ -497,6 +661,250 @@
"resolved": "https://registry.npmjs.org/gitbook-plugin-insert-logo/-/gitbook-plugin-insert-logo-0.1.5.tgz",
"integrity": "sha1-2q6N2kGiNtVPE5MeVwsmcpVXiFo="
},
"gitbook-plugin-mermaid": {
"version": "0.0.9",
"resolved": "https://registry.npmjs.org/gitbook-plugin-mermaid/-/gitbook-plugin-mermaid-0.0.9.tgz",
"integrity": "sha1-l3EKopRojUoex1+whZGb1rpS6/k=",
"requires": {
"phantom": "^0.8.3",
"phantomjs": "~1.9.18",
"q": "1.1.2"
},
"dependencies": {
"assert-plus": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz",
"integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ="
},
"async": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz",
"integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==",
"requires": {
"lodash": "^4.17.11"
}
},
"aws-sign2": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz",
"integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8="
},
"caseless": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz",
"integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c="
},
"concat-stream": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.0.tgz",
"integrity": "sha1-U/fUPFHF5D+ByP3QMyHGMb5o1hE=",
"requires": {
"inherits": "~2.0.1",
"readable-stream": "~2.0.0",
"typedarray": "~0.0.5"
}
},
"debug": {
"version": "0.7.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz",
"integrity": "sha1-BuHqgILCyxTjmAbiLi9vdX+Srzk="
},
"extract-zip": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.5.0.tgz",
"integrity": "sha1-ksz22B73Cp+kwXRxFMzvbYaIpsQ=",
"requires": {
"concat-stream": "1.5.0",
"debug": "0.7.4",
"mkdirp": "0.5.0",
"yauzl": "2.4.1"
}
},
"form-data": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-1.0.1.tgz",
"integrity": "sha1-rjFduaSQf6BlUCMEpm13M0de43w=",
"requires": {
"async": "^2.0.1",
"combined-stream": "^1.0.5",
"mime-types": "^2.1.11"
}
},
"fs-extra": {
"version": "0.26.7",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz",
"integrity": "sha1-muH92UiXeY7at20JGM9C0MMYT6k=",
"requires": {
"graceful-fs": "^4.1.2",
"jsonfile": "^2.1.0",
"klaw": "^1.0.0",
"path-is-absolute": "^1.0.0",
"rimraf": "^2.2.8"
}
},
"har-validator": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz",
"integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=",
"requires": {
"chalk": "^1.1.1",
"commander": "^2.9.0",
"is-my-json-valid": "^2.12.4",
"pinkie-promise": "^2.0.0"
}
},
"http-signature": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz",
"integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=",
"requires": {
"assert-plus": "^0.2.0",
"jsprim": "^1.2.2",
"sshpk": "^1.7.0"
}
},
"lodash": {
"version": "4.17.11",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
"integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="
},
"minimist": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
},
"mkdirp": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz",
"integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=",
"requires": {
"minimist": "0.0.8"
}
},
"node-uuid": {
"version": "1.4.8",
"resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz",
"integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc="
},
"oauth-sign": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
"integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM="
},
"phantom": {
"version": "0.8.4",
"resolved": "https://registry.npmjs.org/phantom/-/phantom-0.8.4.tgz",
"integrity": "sha1-zNtT2IqSN/01UZEnfFjZdwWqr/0=",
"requires": {
"dnode": ">=1.2.2",
"shoe": "~0.0.15",
"traverse": "~0.6.3",
"win-spawn": "~2.0.0"
}
},
"phantomjs": {
"version": "1.9.20",
"resolved": "https://registry.npmjs.org/phantomjs/-/phantomjs-1.9.20.tgz",
"integrity": "sha1-RCSsog4U0lXAsIia9va4lz2hDg0=",
"requires": {
"extract-zip": "~1.5.0",
"fs-extra": "~0.26.4",
"hasha": "^2.2.0",
"kew": "~0.7.0",
"progress": "~1.1.8",
"request": "~2.67.0",
"request-progress": "~2.0.1",
"which": "~1.2.2"
}
},
"process-nextick-args": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
"integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
},
"q": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/q/-/q-1.1.2.tgz",
"integrity": "sha1-Y1fikSBnAdmfGXq4TlforRlvKok="
},
"qs": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/qs/-/qs-5.2.1.tgz",
"integrity": "sha1-gB/uAw4LlFDWOFrcSKTMVbRK7fw="
},
"readable-stream": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
"integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=",
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
"isarray": "~1.0.0",
"process-nextick-args": "~1.0.6",
"string_decoder": "~0.10.x",
"util-deprecate": "~1.0.1"
}
},
"request": {
"version": "2.67.0",
"resolved": "https://registry.npmjs.org/request/-/request-2.67.0.tgz",
"integrity": "sha1-ivdHgOK/EeoK6aqWXBHxGv0nJ0I=",
"requires": {
"aws-sign2": "~0.6.0",
"bl": "~1.0.0",
"caseless": "~0.11.0",
"combined-stream": "~1.0.5",
"extend": "~3.0.0",
"forever-agent": "~0.6.1",
"form-data": "~1.0.0-rc3",
"har-validator": "~2.0.2",
"hawk": "~3.1.0",
"http-signature": "~1.1.0",
"is-typedarray": "~1.0.0",
"isstream": "~0.1.2",
"json-stringify-safe": "~5.0.1",
"mime-types": "~2.1.7",
"node-uuid": "~1.4.7",
"oauth-sign": "~0.8.0",
"qs": "~5.2.0",
"stringstream": "~0.0.4",
"tough-cookie": "~2.2.0",
"tunnel-agent": "~0.4.1"
}
},
"string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
},
"tough-cookie": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.2.2.tgz",
"integrity": "sha1-yDoYMPTl7wuT7yo0iOck+N4Basc="
},
"tunnel-agent": {
"version": "0.4.3",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz",
"integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us="
},
"which": {
"version": "1.2.14",
"resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz",
"integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=",
"requires": {
"isexe": "^2.0.0"
}
}
}
},
"gitbook-plugin-mermaid-gb3": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/gitbook-plugin-mermaid-gb3/-/gitbook-plugin-mermaid-gb3-2.1.0.tgz",
"integrity": "sha512-xCvOWNqkrVrWcBMDGT0ANWlut4GKVzzHh834zy8Ti4Bv7kvGtqA72ykuxBRcJUS+eSVDJNkaQ5D1wF6CNZH9rw==",
"requires": {
"mermaid": "^7.0.7"
}
},
"gitbook-plugin-page-toc": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/gitbook-plugin-page-toc/-/gitbook-plugin-page-toc-1.1.1.tgz",
@ -553,11 +961,40 @@
"markdown-toc": "^0.11.0"
}
},
"glob": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
"integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"graceful-fs": {
"version": "4.1.15",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz",
"integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA=="
},
"graphlib": {
"version": "2.1.7",
"resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.7.tgz",
"integrity": "sha512-TyI9jIy2J4j0qgPmOOrHTCtpPqJGN/aurBwc6ZT+bRii+di1I+Wv3obRhVrmBEXet+qkMaEX67dXrwsd3QQM6w==",
"requires": {
"lodash": "^4.17.5"
}
},
"graphlibrary": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/graphlibrary/-/graphlibrary-2.2.0.tgz",
"integrity": "sha512-XTcvT55L8u4MBZrM37zXoUxsgxs/7sow7YSygd9CIwfWTVO8RVu7AYXhhCiTuFEf+APKgx6Jk4SuQbYR0vYKmQ==",
"requires": {
"lodash": "^4.17.5"
}
},
"gray-matter": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-2.1.1.tgz",
@ -584,6 +1021,14 @@
"har-schema": "^2.0.0"
}
},
"has-ansi": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
"integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
"requires": {
"ansi-regex": "^2.0.0"
}
},
"hasha": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/hasha/-/hasha-2.2.0.tgz",
@ -593,6 +1038,45 @@
"pinkie-promise": "^2.0.0"
}
},
"hawk": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz",
"integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=",
"requires": {
"boom": "2.x.x",
"cryptiles": "2.x.x",
"hoek": "2.x.x",
"sntp": "1.x.x"
},
"dependencies": {
"boom": {
"version": "2.10.1",
"resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz",
"integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=",
"requires": {
"hoek": "2.x.x"
}
},
"cryptiles": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz",
"integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=",
"requires": {
"boom": "2.x.x"
}
},
"hoek": {
"version": "2.16.3",
"resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
"integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0="
}
}
},
"he": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
},
"hoek": {
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.2.tgz",
@ -648,6 +1132,15 @@
"sshpk": "^1.7.0"
}
},
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"requires": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
@ -658,6 +1151,23 @@
"resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
"integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik="
},
"is-my-ip-valid": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz",
"integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ=="
},
"is-my-json-valid": {
"version": "2.19.0",
"resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.19.0.tgz",
"integrity": "sha512-mG0f/unGX1HZ5ep4uhRaPOS8EkAY8/j6mDRMJrutq4CqhoJWYp7qAlonIPy3TV7p3ju4TK9fo/PbnoksWmsp5Q==",
"requires": {
"generate-function": "^2.0.0",
"generate-object-property": "^1.1.0",
"is-my-ip-valid": "^1.0.0",
"jsonpointer": "^4.0.0",
"xtend": "^4.0.0"
}
},
"is-plain-object": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
@ -666,6 +1176,11 @@
"isobject": "^3.0.1"
}
},
"is-property": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
"integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ="
},
"is-stream": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
@ -763,6 +1278,16 @@
"graceful-fs": "^4.1.6"
}
},
"jsonify": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
"integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM="
},
"jsonpointer": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz",
"integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk="
},
"jsprim": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
@ -840,6 +1365,19 @@
}
}
},
"mermaid": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/mermaid/-/mermaid-7.1.2.tgz",
"integrity": "sha512-bDLu3fQuf3/R0fNkNzB0GTaF7+6SxnZpfTs9DVQF1ougsuP23MBzvEIGfL0ML8zeyg7+J2D+0AaoLVhskW5ulw==",
"requires": {
"d3": "3.5.17",
"dagre-d3-renderer": "^0.4.25",
"dagre-layout": "^0.8.0",
"he": "^1.1.1",
"lodash": "^4.17.4",
"moment": "^2.20.1"
}
},
"mime-db": {
"version": "1.38.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz",
@ -853,6 +1391,14 @@
"mime-db": "~1.38.0"
}
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"requires": {
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "0.0.10",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
@ -892,11 +1438,27 @@
}
}
},
"moment": {
"version": "2.24.0",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
"integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg=="
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
"nan": {
"version": "2.13.1",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.13.1.tgz",
"integrity": "sha512-I6YB/YEuDeUZMmhscXKxGgZlFnhsn5y0hgOZBadkzfTRrZBtJDZeg6eQf7PYMIEclwmorTKK8GztsyOUSVBREA==",
"optional": true
},
"node-uuid": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.3.3.tgz",
"integrity": "sha1-09tNe1aBDZ5AMjQnZigq8HORcps="
},
"npm": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/npm/-/npm-5.1.0.tgz",
@ -4940,6 +5502,14 @@
"isobject": "^3.0.1"
}
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"requires": {
"wrappy": "1"
}
},
"optimist": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
@ -4986,6 +5556,11 @@
"integrity": "sha1-m387DeMr543CQBsXVzzK8Pb1nZQ=",
"optional": true
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
},
"pend": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
@ -5157,6 +5732,14 @@
"throttleit": "^1.0.0"
}
},
"rimraf": {
"version": "2.6.3",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
"integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
"requires": {
"glob": "^7.1.3"
}
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
@ -5178,6 +5761,45 @@
"resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
"integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8="
},
"shoe": {
"version": "0.0.15",
"resolved": "https://registry.npmjs.org/shoe/-/shoe-0.0.15.tgz",
"integrity": "sha1-uu2PGn8I9TC2bwkUKH/KplsSRDo=",
"requires": {
"sockjs": "0.3.7",
"sockjs-client": "*"
},
"dependencies": {
"sockjs-client": {
"version": "0.0.0-unreleasable",
"bundled": true
}
}
},
"sntp": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz",
"integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=",
"requires": {
"hoek": "2.x.x"
},
"dependencies": {
"hoek": {
"version": "2.16.3",
"resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
"integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0="
}
}
},
"sockjs": {
"version": "0.3.7",
"resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.7.tgz",
"integrity": "sha1-KVDgWG2KnTBElYqDGt5o2xl3Scs=",
"requires": {
"faye-websocket": "0.4.4",
"node-uuid": "1.3.3"
}
},
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@ -5218,6 +5840,24 @@
"safe-buffer": "~5.1.0"
}
},
"stringstream": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz",
"integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA=="
},
"strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"requires": {
"ansi-regex": "^2.0.0"
}
},
"supports-color": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
},
"symbol-tree": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz",
@ -5264,6 +5904,11 @@
"integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=",
"optional": true
},
"traverse": {
"version": "0.6.6",
"resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz",
"integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc="
},
"tunnel-agent": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
@ -5345,6 +5990,16 @@
"extsprintf": "^1.2.0"
}
},
"weak": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/weak/-/weak-1.0.1.tgz",
"integrity": "sha1-q5mqswcGlZqgIAy4z1RbucszuZ4=",
"optional": true,
"requires": {
"bindings": "^1.2.1",
"nan": "^2.0.5"
}
},
"webidl-conversions": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-2.0.1.tgz",
@ -5368,6 +6023,11 @@
"isexe": "^2.0.0"
}
},
"win-spawn": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/win-spawn/-/win-spawn-2.0.0.tgz",
"integrity": "sha1-OXopEw7JjQqgvIa6pGITk+/9Cwc="
},
"winston": {
"version": "2.4.4",
"resolved": "https://registry.npmjs.org/winston/-/winston-2.4.4.tgz",
@ -5387,12 +6047,22 @@
"integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=",
"optional": true
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
},
"xml-name-validator": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-2.0.1.tgz",
"integrity": "sha1-TYuPHszTQZqjYgYb7O9RXh5VljU=",
"optional": true
},
"xtend": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
"integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="
},
"yauzl": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz",

View File

@ -11,6 +11,8 @@
"gitbook-plugin-custom-favicon": "0.0.4",
"gitbook-plugin-ga": "^1.0.1",
"gitbook-plugin-insert-logo": "^0.1.5",
"gitbook-plugin-mermaid": "0.0.9",
"gitbook-plugin-mermaid-gb3": "^2.1.0",
"gitbook-plugin-page-toc": "^1.1.0",
"gitbook-plugin-panel": "^0.0.1",
"gitbook-plugin-sequence-diagrams": "^1.1.0",

View File

@ -1,59 +1,103 @@
{% panel style="warning", title="Experimental" %}
This chapter contains some recommendations that are actively being explored, and may evolve.
{% panel style="warning", title="Experimental Conventions" %}
Conventions in this chapter may evolve.
{% endpanel %}
{% panel style="info", title="TL;DR" %}
- Use separate branches for separate Environments to
- **Decouple version specific and live operational specific changes** to Resource Config
- Clean audit log of changes to the Environment
- Facilitate Rollbacks to an Environment by reverting commits
Decouple changes to Config to be deployed to separate Environments.
{% endpanel %}
# Branch Structure Based Layout
## Motivation
This chapter describes *conventions* for using **Branches** with Directories.
**Advantages:**
- Flexibility
- Loose coupling between:
- Version dependent changes made when changes are introduced to the code (e.g. adding flags, adding StatefulSets)
- Operational dependent changes for tuning a production environment (e.g. cpu reservations, flag enabling features)
- Simple to view changes for a specific Environment in *git*
- Simple to rollback changes for a specific Environment using *git*
- Trigger Webhooks scoped to specific Environments
**Drawbacks:**
- More complicated to setup and configure. Requires and understanding of using git branches to manage Resource Config.
{% method %}
**Why use branches?** Decouple changes that are rolled out with releases (e.g. new flags) from changes that are
rolled out in response to production events (e.g. resource tuning).
## Branch Structure
### Resource Config
The convention shown here should be changed and adapted as needed.
| Branch Type Name | Deployed to a Cluster | Purpose | Example Config Change | Example Branch Name |
|----------------------------------------|----|-----------|--------|----|
| Base | **No**. Merged into other Branches only. | Changes that should be rolled out as part of a release. | Add *pubsub topic* flag | `master`, `release-1.14`, `i1026` |
| Deploy | **Yes**. - Manually or Continuously. | Base + Changes required to respond to "production" events (or dev, staging, etc). | Increase *memory resources* - e.g. for crashing Containers | `deploy-test`, `deploy-staging`, `deploy-prod` |
| Branch Type Name | Purpose | Examples |
|----------------------------------------|-----------------------|----|
| Base | Contains shared Bases for all deploy environments and version dependent configuration. When new code is added that requires additional configuration, this branch is updated. **This Resource Config is never deployed directly.** | `master`, `release-1.14`, `i1026` |
| Deploy | Contains relevant Config from the Base to be referred to as Bases from `kustomization.yaml`s. Rather than directly modifying the directories from the Base branch, Deploy branches contain separate directories with customizations overlayed on the Base branch directories. **Resource Config only ever gets deployed from these branches.** | `deploy-test`, `deploy-staging`, `deploy-prod` |
Use with techniques described in [Directories](structure_directories.md) and [Branches](structure_branches.md)
## Workflow Example
Summary of workflow with Branches:
1. Live Prod App version is *v1*
1. Changes are introduced to Base Branch Config
- To be release with version *v2*
1. Outage requires changes to the Config running in Prod (*v1*)
1. Prod Branch Config Updated (*v1*)
- Deployed immediately by continuous deployment
1. *v2* changes are rolled out with the *v2* release
- Tag on Base Branch merged into Prod Branch
- Prod Branch continuously deployed
Structure:
### Diagram
- Create (e.g. `master`, `app-version`, etc) a Base branch for version dependent Config changes which
will be used as a Base for deployment dependent Config.
- May have a similar structure to [Directories](structure_directories.md) approach.
- Create separate Deploy branches for separate deployment Environments.
- Create a **new Directory in each branch containing only the deployment specific overlays** - e.g. `deploy-<env>`.
- Create `kustomization.yaml`'s and refer to the version dependent.
{% sequence width=1000 %}
participant Base Branch as BB
participant Staging Branch as SB
participant Staging Clusters as SC
participant Prod Branch as PB
participant Prod Clusters as PC
Note over SC: At v1 release
Note over PC: At v1 release
Note left of BB: Bob: App Dev
Note over BB: Bob Adds Flag
Note over BB: Bob Tags v2
Note over SB: Bob Releases v2
BB-->SB: Merge v2
SB-->SC: Deploy
Note over SC: At v2 release
Note over BB,PC: Prod Outage
Note left of PB: Alice: App SRE
Note over PB: Alice fixes Config
PB-->PC: Alice's changes (only)
Note over PC: At v1* release
Note over BB,PC: Prod Outage resolved
Note over PB: Alice Releases v2
BB-->PB: Merge v2
PB-->PC: Deploy v2
Note over PC: At v2 release
{% endsequence %}
### Description
**Note:** Starting version of Application is *v1*
1. Developer Bob introduces new app flag for release with *v2*
- e.g. PubSub topic name
1. Bob updates the Base Config with the new flag
- Add staging topic for Staging (e.g. `staging-topic`)
- Add prod topic for Prod (e.g. `prod-topic`)
- Flag should be rolled out with *v2* release
1. *v2* is cut
- Base tagged with *v2* tag
1. *v2* rolled out to Staging
- Merge *v2* Tag -> Staging Branch
- Deploy Staging Branch to Staging Clusters
1. SRE Alice identifies issue in Prod (at *v1*)
- Fix is to increase memory of containers
1. Alice updates the Prod branch Config by increasing memory resources
- Changes go directly into Prod Branch without going into Base
1. *v1* changes rolled out to Prod (*v1++*)
- Include Alice's changes, but not Bob's
1. *v2* rolled out to Prod
- Merge *v2* Tag -> Prod Branch
- Deploy Prod Branch to Prod Clusters
{% method %}
Techniques:
@ -64,9 +108,18 @@ Techniques:
- Will be rolled out immediately independent of versions.
- Merge code from the Base branch to the Deploy branches to perform a Rollout.
## Directory and Branch Layout
Structure:
- Base branch (e.g. `master`, `app-version`, etc) for Config changes tied to releases.
- Looks like [Directories](structure_directories.md)
- Separate Deploy branches for separate Environments (e.g. `deploy-<env>`).
- A new **Directory in each branch with will contain overlay customizations** - e.g. `deploy-<env>`.
{% sample lang="yaml" %}
**Base Branch:**
**Base Branch:** `master`
```bash
tree
@ -98,22 +151,30 @@ tree
**Deploy Branches:**
Prod Branch: `deploy-prod`
```bash
tree
.
├── bases # From Base Branch
│   ├── ...
├── prod # From Base Branch
│   ├── ...
│   └── ...
└── deploy-prod # Prod deploy folder
   ├── us-central
   │   ├── kustomization.yaml # Uses bases: ["../../prod/us-central"]
   ├── us-east
   │   └── kustomization.yaml # Uses bases: ["../../prod/us-east"]
└── us-west
└── kustomization.yaml # Uses bases: ["../../prod/us-west"]
│   ├── us-central
│   │   ├── kustomization.yaml # Uses bases: ["../../prod/us-central"]
│   ├── us-east
│   │   └── kustomization.yaml # Uses bases: ["../../prod/us-east"]
│ └── us-west
│ └── kustomization.yaml # Uses bases: ["../../prod/us-west"]
├── prod # From Base Branch
│   └── ...
├── staging # From Base Branch
│   └── ...
└── test # From Base Branch
└── ...
```
Staging Branch: `deploy-staging`
```bash
tree
.
@ -122,10 +183,16 @@ tree
├── deploy-staging # Staging deploy folder
│ └── us-west
│ └── kustomization.yaml # Uses bases: ["../../staging/us-west"]
└── staging # From Base Branch
   └── ...
├── prod # From Base Branch
│   └── ...
├── staging # From Base Branch
│   └── ...
└── test # From Base Branch
└── ...
```
Test Branch: `deploy-test`
```bash
tree
.
@ -134,109 +201,66 @@ tree
├──deploy-test # Test deploy folder
│ └── us-west
│ └── kustomization.yaml # Uses bases: ["../../test/us-west"]
├── prod # From Base Branch
│   └── ...
├── staging # From Base Branch
│   └── ...
└── test # From Base Branch
└── ...
```
{% endmethod %}
{% panel style="success", title="Promotion from the Base branch to Deploy branches" %}
## Rollback Workflow Example
- If a user's application source code and Resource Config are both in the Base branch, user's may want
to only merge the Resource Config. This could be done using `git checkout` - e.g.
`git checkout <base-branch> bases/ prod/`
Summary of rollback workflow with Branches:
- Instead of merging from the Base branch directly, users can create Deploy branches of the Base.
Alternatively, users can tag the Base branch commits as deploys and check these out.
1. Live Prod App version is *v1*
1. Changes are introduced to Base Branch Config
- To be released with version *v2*
1. Release *v2* is cut to be rolled out
- Tag Base *v2* and build artifacts (e.g. images)
1. Changes are introduced into the Base Branch Confiug
- To be released with version *v3*
1. *v2* is pushed to Prod (eventually)
- *v2* Tag merged into Prod Branch
1. *v2* has issues in Prod and must be rolled back
- *v2* changes are rolled back in new commit to Prod Branch
1. Base Branch is unaffected
- Fix introduced in *v3*
{% endpanel %}
**Note:** New changes committed to the Base for "v3" did not make the rollback from
"v2" -> "v1" more challenging, as they had not been merged into the Prod Branch.
{% method %}
### Diagram
## Alternative Branch Structure
{% sequence width=1000 %}
An alternative to the above structure is to use branches similar to how *GitHub Pages* branches
functions - where code is not merged between branches and is similar to having a new repository.
participant Base Branch as BB
participant Staging Branch as SB
participant Staging Clusters as SC
participant Prod Branch as PB
participant Prod Clusters as PC
This approach looks very similar to the [Repository Based Structure](structure_repositories.md), but
using branches instead of Repositories.
Note over SC: At v1 release
Note over PC: At v1 release
Note left of BB: Bob: App Dev
Note over BB: Bob Adds Flag (for v2)
Note over BB: Bob Tags v2
Note over SB: Bob Releases v2
BB-->SB: Merge v2
SB-->SC: Deploy
Note over SC: At v2 release
Note over SB: Bob Adds another Flag (for v3)
Note over PB: Bob Releases v2
BB-->PB: Merge v2
PB-->PC: Deploy v2
Note over PC: At v2 release
Note over BB,PC: Unrelated Prod Outage
Note left of PB: Alice: App SRE
Note over PB: Alice rolls back v2 merge
PB-->PC: Deploy v1
Note over PC: At v1 release
Note over BB,PC: Prod Outage resolved
- Use a Base (e.g. master, deploy-version, etc) branch for configuration tightly coupled to releasing new code.
- Looks like [Directories](structure_directories.md) approach.
- Create separate branches for deploying to different Environments.
- Create a **new Directory for the Deploy overlays** - e.g. `deploy-<env>`.
- Base Branch is never merge. Deploy overlays refer to Bases as remote urls.
Techniques:
- Add new required flags and environment variables to the Resource Config in the base branch at the
time they are added to the code.
- Will be rolled out when the code is rolled out.
- Adjust flags and configuration to the Resource Config in the Deploy branch in the deploy directory.
- Will be rolled out immediately independent of deploys.
- Tag the base branch with deploys.
- Deploy branches use tagged references as their bases.
{% sample lang="yaml" %}
**Base Branch:**
```bash
tree
.
├── bases
│   ├── ...
├── prod
│   ├── bases
│   │   ├── ...
│   ├── us-central
│   │   ├── kustomization.yaml
│   │   └── backend
│   │   └── deployment-patch.yaml
│   ├── us-east
│   │   └── kustomization.yaml
│   └── us-west
│   └── kustomization.yaml
├── staging
│   ├── bases
│   │   ├── ...
│   └── us-west
│   └── kustomization.yaml
└── test
├── bases
│   ├── ...
└── us-west
└── kustomization.yaml
```
**Deploy Branches:**
```bash
tree
.
└── deploy-prod
   ├── us-central
   │   ├── kustomization.yaml
   ├── us-east
   │   └── kustomization.yaml
└── us-west
└── kustomization.yaml
```
```bash
tree
.
└── deploy-staging
└── us-west
└── kustomization.yaml
```
```bash
tree
.
└── deploy-test
└── us-west
└── kustomization.yaml
```
{% endmethod %}
{% endsequence %}

View File

@ -7,35 +7,11 @@
## Motivation
This chapter describes *conventions* when using **Directories** alone - without Branches or Repositories.
{% panel style="success", title="Which is right for my organization?" %}
While this chapter is focussed on conventions when using Directories alone, these same conventions should
also be used with Branches or Repositories.
For complex deployment environments where responsibility over Config spans responsibilities or abstraction
layers owned by separate teams - modularization and isolation between teams may be necessary -
(which may include using Branches and Repositories, or other techniques).
While this chapter is focused on conventions when using Directories, Branches and
Repositories should be used with Directories as needed.
{% endpanel %}
**Advantages:**
- Simplicity
- Simple to learn
- Simple to navigate using conventional tools
- Simple to audit
**Drawbacks:**
- Limited permissions and ownership models
- Read/Write access typically given at a per-repo model
- Less granular event triggers
- Webhooks triggered for repo+branch can't be focused on a specific environment + cluster
- Harder to decouple release related changes from operational related changes
- Changes to scale or cpu should be rolled out immediately
- Changes to image or flags should be rolled out with the release
{% panel style="info", title="Config Repo or Mono Repo?" %}
The techniques and conventions in this Chapter work regardless of whether or not the Resource Config
exists in the same Repository as the source code that is being deployed.
@ -43,19 +19,57 @@ exists in the same Repository as the source code that is being deployed.
## Directory Structure
| Dir Type | Deployed to a Cluster | Contains | Example Names |
|----------------|----------------------------------|----------|---------------|
| Base | **No** - Used as base | Shared Config. | `base/` |
| Env | **No** - Contains other dirs | Base and Cluster dirs. | `test/`, `staging/`, `prod/` |
| Cluster | **Yes** - Manually or Continuously | Deployable Config. | `us-west1`, `us-east1`, `us-central1` |
## Workflow Example
- Changes made to *env/cluster/* roll out to **only that specific env-cluster**
- Changes made to *env>/bases/* roll out to **all clusters for that env**
- Changes made to *bases/* roll out to **all clusters in all envs**
## Diagram
```mermaid
graph TD;
B("bases/ ")---|base|P("prod/bases/ ");
B("bases/ ")---|base|S("staging/bases/ ");
B("bases/ ")---|base|T("test/bases/ ");
P("prod/bases/ ")---|base|PUW("prod/us-west/ ");
P("prod/bases/ ")---|base|PUE("prod/us-east/ ");
P("prod/bases/ ")---|base|PUC("prod/us-central/ ");
S("staging/bases/ ")---|base|SUW("staging/us-west/ ");
T("test/bases/ ")---|base|TUW("test/us-west/ ");
```
{% sequence width=1000 %}
participant Config in Git as B
participant Test Cluster as TC
participant Staging Cluster as SC
participant US West Prod Cluster as WC
participant US East Prod Cluster as EC
Note over B: Alice modifies prod/us-west1 with change A
B-->WC: A deployed
Note over B: Alice modifies prod/bases with change B
B-->EC: B deployed
B-->WC: B deployed
Note over B: Alice modifies bases/ with change C
B-->EC: C deployed
B-->TC: C deployed
B-->WC: C deployed
B-->SC: C deployed
{% endsequence %}
{% method %}
### Resource Config
The convention shown here should be changed and adapted as needed.
Structure:
- Put reusable bases under `*/bases/`
- `<project-name>/bases/`
- `<project-name>/<environment>/bases/`
- Put deployable targets under `<project-name>/<environment>/<cluster>/`
Techniques:
- Each Layer adds a [namePrefix](../app_management/namespaces_and_names.md#setting-a-name-prefix-or-suffix-for-all-resources) and [commonLabels](../app_management/labels_and_annotations.md#setting-labels-for-all-resources).
@ -64,6 +78,13 @@ Techniques:
- Override [Pod Environment Variables and Arguments](../app_customization/customizing_pod_templates.md) using `configMapGenerator`s with `behavior: merge`.
- Perform Last-mile customizations with [patches / overlays](../app_customization/customizing_arbitrary_fields.md)
Structure:
- Put reusable bases under `*/bases/`
- `<project-name>/bases/`
- `<project-name>/<environment>/bases/`
- Put deployable targets under `<project-name>/<environment>/<cluster>/`
{% sample lang="yaml" %}
```bash
@ -123,4 +144,30 @@ For more information see [Multi-Cluster](accessing_multiple_clusters.md).
{% panel style="success", title="Code Owners" %}
Some git hosting services provide the concept of *Code Owners* for providing a finer grain permissions model.
*Code Owners* may be used to provide separate permissions for separate environments - e.g. dev, test, prod.
{% endpanel %}
{% endpanel %}
## Rollback Diagram
{% sequence width=1000 %}
participant Config in Git as B
participant Test Cluster as TC
participant Staging Cluster as SC
participant US West Prod Cluster as WC
participant US East Prod Cluster as EC
Note over B: Bob modifies bases/ with change B
B-->EC: B deployed
B-->SC: B deployed
B-->WC: B deployed
Note over B,EC: Prod Outage caused by B
B-->TC: B deployed
Note over B: Bob rolls back bases/ to A
B-->WC: A deployed
B-->TC: A deployed
B-->EC: A deployed
Note over B,EC: Prod Outage resolved
B-->SC: A deployed
{% endsequence %}

View File

@ -8,34 +8,32 @@
The chapters in this section cover how to structure Resource Config using git.
Users may start with a pure Directory Hierarchy approach, and migrate to include Branches
Users may start with a pure Directory Hierarchy approach, and later include Branches
and / or Repositories as part of the structure.
## Background
Tools:
Terms:
- *Bases:* provide **common or shared Resource Config to be factored out** that can be
imported into multiple projects.
- *Overlays and Customizations:* tailor **common or shared Resource Config to be modified** to
a specific application, environment or purpose.
Applied Concepts:
| Technique | Decouple Changes | Used For | Workflow |
|---------------------------------------------|-----------------------------|----------------------------------------------------|----------|
| [Directories](structure_directories.md) | NA | Foundational structure. | Changes are immediately propagated globally. |
| [Branches](structure_branches.md) | *Across Environments* | Promoting changes across Environments. | Changes are promoted across linear stages. |
| [Repositories](structure_repositories.md) | *Across Teams* | Fetching changes across config shared across Teams. | Changes are pulled by consumers (like upgrades). |
- Resource Config may be initially structured using Directory Hierarchy for organization.
Concepts:
- Resource Config may be initially structured using only Directory Hierarchy for organization.
- Use Bases with Overlays / Customizations for factoring across Directories
- Different Deployment environments for the same app may be loosely coupled, using separate **Branches for separate
environments**.
- Different Deployment environments for the same app may be loosely coupled
- Use separate **Branches for separate environments**.
- Use Bases with Overlays / Customization for factoring across Branches
- Teams owning separate (shared) Config may be loosely coupled using separate **Repositories for
separate teams**.
- Different Teams owning sharing Config may be loosely coupled
- Use separate **Repositories for separate teams**.
- Use Bases with Overlays / Customization for factoring across Repositories
Table:
| Technique | Decouple Changes | Best For | Workflow |
|---------------------------------------------|-----------------------|----------------------------------------------------|----------|
| [Directories](structure_directories.md) | NA | Simple organizational and deployment structure. | Changes are immediately propagated globally. |
| [Branches](structure_branches.md) | *Across Environments* | Promoting changes across Environments. | Changes to Bases are pushed across multiple linear stages by the owners of Bases. |
| [Repositories](structure_repositories.md) | *Across Teams* | Fetching changes across config shared across Teams. | Changes to Bases are pulled by individual consumers into their projects. |

View File

@ -14,6 +14,15 @@ Users may want to reuse the **same base multiple times within the same Apply Pro
## 3-Tier Composition
```mermaid
graph TD;
B("Generic Base ")---|base|A1("App 1 ");
B("Generic Base ")---|base|A2("App 2 ");
A1("App 1 ")---|base|C("Composite App ");
A2("App 2 ")---|base|C("Composite App ");
```
{% method %}
It is possible to reuse the same base multiple times within the same project by using a 3-tier
structure to compose multiple Variants of the base.

View File

@ -1,22 +1,16 @@
{% panel style="warning", title="Experimental" %}
This chapter contains some recommendations that are actively being explored, and may evolve.
{% panel style="warning", title="Experimental Conventions" %}
Conventions in this chapter may evolve.
{% endpanel %}
{% panel style="info", title="TL;DR" %}
- Finer grain management using separate repos for separate Team
- Separate permissions for committing changes to separate environments
- Separate Issue, Project and PR tracking
Decouple changes to Config owned by separate Teams.
{% endpanel %}
# Repository Structure Based Layout
## Motivation
This chapter describes *conventions* for using **Repositories** with Directories.
**Advantages:**
- **Isolation between teams** managing separate Environments
- Permissions
- **Fine grain control** over
@ -24,125 +18,88 @@ This chapter describes *conventions* for using **Repositories** with Directories
- Issues
- Projects
- Automation
**Drawbacks:**
- Tools designed to work with files and directories don't work across Repositories
- Complicated to setup and manage
- **Harder to reason about the system as a whole**
- State spread across multiple Repositories
## Directory Structure
### Resource Config
| Repo Type | Deployed to a Cluster | Contains | Example Names |
|-----------------|------------------------------------|----------|---------------|
| Base | **No** - Used as Base | Config shared with other teams. | `platform` |
| App | **Yes** - Manually or Continuously | Deployable Config. | `guest-book` |
Use with techniques described in [Directories](structure_directories.md) and [Branches](structure_branches.md)
## Workflow Example
1. Alice on the Java Platform team updates the Java Base used by other teams
1. Alice creates a Git Tag for the new release
1. Bob on the GuestBook App team switches to the new Java Base by updating the referene
## Diagram
{% sequence width=1000 %}
participant Base Repo as BR
participant App Repo as AR
participant Cluster as C
Note left of BR: Alice: Platform Dev
Note over BR: Alice modifies java Base
Note over BR: Alice tags java Base v2
Note left of AR: Bob: App Dev
Note over AR: Uses java Base v1
BR-->AR: Bob updates to reference Base v2
Note over AR: Uses java Base v2
AR-->C: java Base v2 changes deployed
{% endsequence %}
{% method %}
{% sample lang="yaml" %}
Structure:
- Platform teams create Base Repositories for shared Config
- App teams create App Repositories for their Apps
- Remotely reference the Base Repository
**Base Repository:** Platform Team
```bash
tree
.
├── bases # Used as a Base only
│   ├── kustomization.yaml
│   └── ...
├── java # Java Bases
│   ├── kustomization.yaml # Uses bases: ["../bases"]
│   └── ...
└── python # Python Bases
```
**App Repository:** GuestBook Team
```bash
tree
.
├── bases # References Base Repositories
│   └── ...
├── prod
│   └── ...
├── staging
│   └── ...
└── test
└── ...
```
{% endmethod %}
{% panel style="info", title="Remote URLs vs Vendoring" %}
- Repositories owned and controlled by the same organization may be referenced to by their URL
- Repositories owned or controlled by separate organizations should be vendored and referenced
by path to the vendor directory.
{% endpanel %}
{% method %}
### Resource Config
The convention shown here should be changed and adapted as needed.
| Repo Type Name | Purpose | Examples |
|----------------------------------------|-----------------------|----|
| Base | Contains shared Bases for all deploy environments and version dependent configuration. When new code is added that requires additional configuration, this repository is updated. **This Resource Config is never deployed directly.** | `app-name` |
| Deploy | Does not contain Config from the Base, rather refers to the Base Config remotely through the git url. Deploy repositories contain directories with similar structure to the Base directories, but instead contain customizations overlayed on the remote Bases. **Resource Config only ever gets deployed from these Repositories.** | `app-name-test`, `app-name-staging`, `app-name-prod` |
Structure:
- Create a Base Repository for shared configuration
- Looks like [Directories](structure_directories.md) approach
- For each **separate Environment, create a separate Deploy Repository**
- Remotely reference the Base Repository in from the Deploy Repository
Techniques:
- Use techniques described in [Directories](structure_directories.md) and [Branches](structure_branches.md)
{% sample lang="yaml" %}
**Base Repository:**
```bash
tree
.
├── bases # Used as a Base only
│   ├── kustomization.yaml
│   ├── backend
│   │   ├── deployment.yaml
│   │   └── service.yaml
│   ├── frontend
│   │   ├── deployment.yaml
│   │   ├── ingress.yaml
│   │   └── service.yaml
│   └── storage
│   ├── service.yaml
│   └── statefulset.yaml
├── prod # Production
│   ├── bases
│   │   ├── kustomization.yaml # Uses bases: ["../../bases"]
│   │   ├── backend
│   │   │   └── deployment-patch.yaml # Production Env specific backend overrides
│   │   ├── frontend
│   │   │   └── deployment-patch.yaml # Production Env specific frontend overrides
│   │   └── storage
│   │   └── statefulset-patch.yaml # Production Env specific storage overrides
│   ├── us-central
│   │   ├── kustomization.yaml # Uses bases: ["../bases"]
│   │   └── backend
│   │   └── deployment-patch.yaml # us-central cluster specific backend overrides
│   ├── us-east
│   │   └── kustomization.yaml # Uses bases: ["../bases"]
│   └── us-west
│   └── kustomization.yaml # Uses bases: ["../bases"]
├── staging # Staging
│   ├── bases
│   │   ├── kustomization.yaml # Uses bases: ["../../bases"]
│   └── us-west
│   └── kustomization.yaml # Uses bases: ["../bases"]
└── test # Test
├── bases
│   ├── kustomization.yaml # Uses bases: ["../../bases"]
└── us-west
└── kustomization.yaml # Uses bases: ["../bases"]
```
**Team Repositories:**
```bash
# sre team
tree
.
├── prod
│   ├── us-central
│   │   ├── kustomization.yaml # Uses bases: ["https://<your-repo>/prod/us-central?ref=<prod-release>"]
│   ├── us-east
│   │   └── kustomization.yaml # Uses bases: ["https://<your-repo>/prod/us-east?ref=<prod-release>"]
│   └── us-west
│   └── kustomization.yaml # Uses bases: ["https://<your-repo>/prod/us-west?ref=<prod-release>"]
```
```bash
# qa team
tree
.
├── staging # Staging
│   └── us-west
│   └── kustomization.yaml # Uses bases: ["https://<your-repo>/staging/us-west?ref=<staging-release>"]
```
```bash
# dev team
tree
.
└── test # Test
└── us-west
└── kustomization.yaml # Uses bases: ["https://<your-repo>/test/us-west?ref=<test-release>"]
```
{% endmethod %}

View File

@ -30,6 +30,26 @@ Bases can be:
- Relative paths from the `kustomization.yaml` - e.g. `../base`
- Urls - e.g. `github.com/kubernetes-sigs/kustomize/examples/multibases?ref=v1.0.6`
### Diagrams
Single Base inheritted by single Application
```mermaid
graph TD;
B[B]-->A[A];
```
Shared Bases inheritted by different Applications
```mermaid
graph TD;
B1[B1]-->A1[A1];
B2[B2]-->A1[A1];
B2[B2]-->A2[A2];
B3[B3]-->A2[A2];
```
{% method %}
**Example:** Add a `kustomization.yaml` as a Base.
@ -129,3 +149,10 @@ spec:
Bases themselves may also be Variants and have their own Bases. See [Advanced Composition](../app_composition_and_deployment/structure_multi_tier_apps.md)
for more information.
{% endpanel %}
```mermaid
graph TD;
B1[B1]-->B2[B2];
B2[B2]-->A[A];
```

View File

@ -100,7 +100,10 @@ spec:
{% endmethod %}
{% panel style="info", title="More Info" %}
{% panel style="info", title="Replacing Images" %}
`newImage` allows an image name to be replaced with another arbitrary image name. e.g. you could
call your image `webserver` or `database` and replace it with `nginx` or `mysql`.
For more information on customizing images, see [Container Images](../app_management/container_images.md).
{% endpanel %}
@ -142,7 +145,7 @@ configMapGenerator:
behavior: merge
literals:
- special.how=some # this value is overridden
- special.other=that # this value is kept
- special.other=that # this value is added
```
```yaml

View File

@ -1,8 +1,8 @@
# Introduction
This section of the book covers how to build Projects and Applications with multiple subcomponents
partially defined by multiple teams or organizations. Apply kustomizations allow the authoring
of Resource Config to be a collaboration across teams.
This section of the book covers how to build Projects and Applications with Config
shared across teams. Apply kustomizations allow the authoring of Resource Config to
be a collaboration across teams.
Kustomizations facilitate:

View File

@ -7,7 +7,11 @@
## Motivation
Apply will update a Kubernetes cluster to match state defined locally in files.
Apply is a command that will update a Kubernetes cluster to match state defined locally in files.
```bash
kubectl apply
```
- Fully declarative - don't need to specify create or update - just manage files
- Merges user owned state (e.g. Service `selector`) with state owned by the cluster (e.g. Service `clusterIp`)
@ -25,10 +29,9 @@ either raw Resource Config or *kustomization.yaml*.
{% method %}
It is recommended to use a `kustomization.yaml` with Apply. `kustomization.yaml` provides low-level
tooling to simplify managing collections of Resources Configs.
This `kustomization.yaml` file contains a Deployment Resource Config which will be Applied.
Though Apply can be run directly against Resource Config files or directories using `-f`, it is recommended
to run Apply against a `kustomization.yaml` using `-k`. The `kustomization.yaml` allows users to define
configuration that cuts across many Resources (e.g. namespace).
{% sample lang="yaml" %}
@ -37,8 +40,17 @@ This `kustomization.yaml` file contains a Deployment Resource Config which will
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
# list of Resource Config to be Applied
resources:
- deployment.yaml
# namespace to deploy all Resources to
namespace: default
# labels added to all Resources
commonLabels:
app: example
env: test
```
```yaml
@ -48,15 +60,18 @@ kind: Deployment
metadata:
name: nginx
labels:
app: nginx
component: nginx
tier: frontend
spec:
selector:
matchLabels:
app: nginx
component: nginx
tier: frontend
template:
metadata:
labels:
app: nginx
component: nginx
tier: frontend
spec:
containers:
- name: nginx

View File

@ -6,8 +6,10 @@
## Motivation
It may be useful to define the tags of container images which are
used across many Workloads.
It may be useful to define the tags or digests of container images which are used across many Workloads.
Container image tags and digests are used to refer to a specific version or instance of a container
image - e.g. for the `nginx` container image you might use the tag `1.15.9` or `1.14.2`.
- Update the container image name or tag for multiple Workloads at once
- Increase visibility of the versions of container images being used within

View File

@ -6,6 +6,10 @@
# Merging Fields
{% panel style="warning", title="Advanced Section" %}
This chapter contains advanced material that readers may want to skip and come back to later.
{% endpanel %}
## When are fields merged?
This page describes how Resource Config is merged with Resources or other Resource Config. This

View File

@ -10,10 +10,27 @@ This section covers how to declaratively manage Workloads and Applications.
Workloads in a cluster may be configured through files called *Resource Config*. These files are
typically checked into source control, and allow cluster state changes to be reviewed before they
are Applied, and audited.
are audited and applied.
There are 2 components to Application Management.
## Client Component
The client component consists of authoring Resource Config which defines the desired state
of an Application. This may be done as a collection of raw Resource Config files, or by
composing and overlaying Resource Config authored by separate teams
(using the `-k` flag with a `kustomization.yaml`).
Kustomize offers low-level tooling for simplifying the authoring of Resource Config. It provides:
- **Generating Resource Config** from other canonical sources - e.g. ConfigMaps, Secrets
- **Reusing and Composing one or more collections of Resource Config**
- **Customizing Resource Config**
- **Setting cross-cutting fields** - e.g. namespace, labels, annotations, name-prefixes, etc
**Example:** One user may define a Base for an application, while another user may customize
a specific instance of the Base.
## Server Component
The server component consists of a human applying the authored Resource Config to the cluster
@ -25,20 +42,3 @@ Note that the process of Application Management is a collaborative one between u
Kubernetes system itself - where each may contribute to defining the desired state.
**Example**: An Autoscaler Controller in the cluster may set the scale field on a Deployment managed by a user.
## Client Component
The client component consists of one or more humans collectively authoring the desired
state of an Application as Resource Config. This may be done as a collection of
raw Resource Config files, or by composing and overlaying Resource Config authored
by separate parties (using the `-k` flag with a `kustomization.yaml`).
Kustomize offers low-level tooling for simplifying the authoring of Resource Config. It provides:
- **Generating Resource Config** from other canonical sources - e.g. ConfigMaps, Secrets
- **Reusing and Composing one or more collections of Resource Config**
- **Customizing Resource Config**
- **Setting cross-cutting fields** - e.g. namespace, labels, annotations, name-prefixes, etc
**Example:** One user may define a Base for an application, while another user may customize
a specific instance of the Base.

View File

@ -161,8 +161,8 @@ ConfigMaps and Secrets in the Pod Spec.
This sets a name prefix or suffix for both generated Resources (e.g. ConfigMaps
and Secrets) and non-generated Resources.
The namePrefix or nameSuffix that is applied is propagated to references within
the Project.
The namePrefix or nameSuffix that is applied is propagated to references to updated resources -
e.g. references to Secrets and ConfigMaps are updated with the namePrefix and nameSuffix.
{% endpanel %}
{% method %}

View File

@ -0,0 +1,203 @@
{% panel style="info", title="TL;DR" %}
- Creating Resources
- Printing Resources
- Debugging Containers
{% endpanel %}
# Getting Started With Kubectl
**Note**: If you are already familiar with Kubectl, you can skip this section.
This section provides a brief overview of the most basic Kubectl commands, which are
described in more detail in later chapters.
For more background on the Kubernetes APIs themselves, see the docs at [k8s.io](k8s.io).
## Listing Kubernetes Resources
{% method %}
List the Kubernetes *Deployment* Resources that are in the kube-system namespace.
**Note:** Deployments are Resources which manage Pod replicas (Pods run Containers)
{% sample lang="yaml" %}
```bash
kubectl get deployments --namespace kube-system
```
```bash
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
event-exporter-v0.2.3 1 1 1 1 14d
fluentd-gcp-scaler 1 1 1 1 14d
heapster-v1.6.0-beta.1 1 1 1 1 14d
kube-dns 2 2 2 2 14d
kube-dns-autoscaler 1 1 1 1 14d
l7-default-backend 1 1 1 1 14d
metrics-server-v0.3.1 1 1 1 1 14d
```
{% endmethod %}
{% method %}
Print detailed information about the kube-dns Deployment in the kube-system namespace.
{% sample lang="yaml" %}
```bash
kubectl describe deployment kube-dns --namespace kube-system
```
```bash
Name: kube-dns
Namespace: kube-system
CreationTimestamp: Wed, 06 Mar 2019 17:36:05 -0800
Labels: addonmanager.kubernetes.io/mode=Reconcile
k8s-app=kube-dns
kubernetes.io/cluster-service=true
Annotations: deployment.kubernetes.io/revision: 2
...
```
{% endmethod %}
## Creating a Resource from Config
{% method %}
Create or Update Kubernetes Resources from Remote Config.
{% sample lang="yaml" %}
```bash
kubectl apply -k https://github.com/kubernetes/kubectl/docs/book/examples/nginx
```
```bash
service/nginx created
deployment.apps/nginx-deployment created
```
{% endmethod %}
{% method %}
Create or Update Kubernetes Resources from Local Config.
{% sample lang="yaml" %}
```bash
kubectl apply -k ./examples/nginx
```
```bash
service/nginx created
deployment.apps/nginx-deployment created
```
{% endmethod %}
{% method %}
Print the Resources that were Applied.
{% sample lang="yaml" %}
```bash
kubectl get -k ./examples/nginx/ --show-labels
```
```bash
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE LABELS
service/nginx ClusterIP 10.59.245.201 <none> 80/TCP 11m <none>
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE LABELS
deployment.apps/nginx-deployment 3 3 3 3 11m app=nginx
```
{% endmethod %}
## Generating a Config from a Command
{% method %}
Generate Config for a Deployment Resource. This could be Applied to a cluster by writing the output
to a file, and then running `kubectl apply -f <yaml-file>`
**Note:** The generated Config has extra boilerplate that users shouldn't include but exists
due to the serialization process of go objects.
{% sample lang="yaml" %}
```bash
kubectl create deployment nginx --dry-run -o yaml --image nginx
```
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null # delete this
labels:
app: nginx
name: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
strategy: {} # delete this
template:
metadata:
creationTimestamp: null # delete this
labels:
app: nginx
spec:
containers:
- image: nginx
name: nginx
resources: {} # delete this
status: {} # delete this
```
{% endmethod %}
## Viewing Pods Associated with Resources
{% method %}
View the Pods created by the Deployment using the Pod labels.
{% sample lang="yaml" %}
```bash
kubectl get pods -l app=nginx
```
```bash
NAME READY STATUS RESTARTS AGE
nginx-deployment-5c689d88bb-b2xfk 1/1 Running 0 10m
nginx-deployment-5c689d88bb-rx569 1/1 Running 0 10m
nginx-deployment-5c689d88bb-s7xcv 1/1 Running 0 10m
```
{% endmethod %}
## Debugging Containers
{% method %}
Get the logs from all Pods managed by the Deployment.
{% sample lang="yaml" %}
```bash
kubectl logs -l app=nginx
```
{% endmethod %}
{% method %}
Get a shell into a specific Pod's Container
{% sample lang="yaml" %}
```bash
kubectl exec -i -t nginx-deployment-5c689d88bb-s7xcv bash
```
```bash
root@nginx-deployment-5c689d88bb-s7xcv:/#
```
{% endmethod %}

View File

@ -1,71 +0,0 @@
{% panel style="info", title="TL;DR" %}
- Kubectl is the Kubernetes cli
- Kubectl provides a swiss army knife of functionality for working with Kubernetes clusters
- Kubectl may be used to deploy and manage applications on Kubernetes
- Kubectl may be used for scripting and building higher-level frameworks
{% endpanel %}
# Kubectl
Kubectl is the Kubernetes cli version of a swiss army knife.
## Command Families
While Kubectl has many different commands, they typically fall into one of a few categories:
| Type | Used For | Description |
|----------------------------------------|-----------------------|----------------------------------------------------|
| Declarative Resource Management | Production Operations and GitOps | Declaratively manage Kubernetes Workloads using Resource Config |
| Imperative Resource Management | Development | Run commands to manage Kubernetes Workloads using Command Line arguments and flags |
| Printing Workload State | Debugging | Print information about Workloads |
| Interacting with Containers | Debugging | Exec, Attach, Cp, Logs |
| Cluster Management | Cluster Ops | Drain and Cordon Nodes |
## Declarative Application Management
The preferred approach for managing Resources is through
declarative files called Resource Config used with the Kubectl *Apply* command.
This command reads a local (or remote) file structure and modifies cluster state to
reflect the declared intent.
{% panel style="info", title="Apply" %}
Apply is the preferred mechanism for managing Resources in a Kubernetes cluster.
{% endpanel %}
## Printing state about Workloads
Users will need to view Workload state.
- Printing summarize state and information about Resources
- Printing complete state and information about Resources
- Printing specific fields from Resources
- Query Resources matching labels
## Debugging Workloads
Kubectl supports debugging by providing commands for:
- Printing Container logs
- Printing cluster events
- Exec or attaching to a Container
- Copying files from Containers in the cluster to a user's filesystem
## Cluster Management
On occasion, users may need to perform operations to the Nodes of cluster. Kubectl supports
commands to drain Workloads from a Node so that it can be decommission or debugged.
## Porcelain
Users may find using Resource Config overly verbose for *Development* and prefer to work with
the cluster *imperatively* with a shell-like workflow. Kubectl offers porcelain commands for
generating and modifying Resources.
- Generating + creating Resources such as Deployments, StatefulSets, Services, ConfigMaps, etc
- Setting fields on Resources
- Editing (live) Resources in a text editor
{% panel style="danger", title="Porcelain For Dev Only" %}
Porcelain commands are time saving for experimenting with workloads in a dev cluster, but shouldn't
be used for production.
{% endpanel %}

View File

@ -4,21 +4,36 @@
- Controllers asynchronously actuate Resources after they are stored
{% endpanel %}
# The Kubernetes Resource Model
# Kubernetes Resources and Controllers Overview
This section provides background on the Kubernetes Resource model. This information
is also available at the [kubernetes.io](https://kubernetes.io/docs/home/) docs site.
For more information on Kubernetes Resources see: [kubernetes.io Concepts](https://kubernetes.io/docs/concepts/).
## Resources
Instances of Kubernetes objects such as
[Deployments](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/),
[StatefulSets](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/),
[Jobs](https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/),
[CronJobs](https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/) and
[DaemonSets](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/) are called **Resources**.
Instances of Kubernetes objects (e.g. Deployment, Services, Namespaces, etc)
are called **Resources**.
**Users work with Resource APIs by declaring them in files called Resource Config.** Resource Config is
*Applied* (declarative Create/Update/Delete) to a Kubernetes cluster, and actuated by a *Controller*.
Resources which run containers are referred to as **Workloads**.
Resources are keyed by:
Examples of Workloads:
- [Deployments](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)
- [StatefulSets](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/)
- [Jobs](https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/)
- [CronJobs](https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/)
- [DaemonSets](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/)
**Users work with Resource APIs by declaring them in files which are then Applied to a Kubernetes
cluster. These declarative files are called Resource Config.**
Resource Config is *Applied* (declarative Create/Update/Delete) to a Kubernetes cluster using
tools such as Kubectl, and then actuated by a *Controller*.
Resources are uniquely identified:
- **apiVersion** (API Type Group and Version)
- **kind** (API Type Name)
@ -133,4 +148,77 @@ Because Controllers don't respond to individual Events, but instead Reconcile th
of the system at the time that Reconcile is run, **changes from several different events may be observed
and Reconciled together.** This is referred to as a *Level Based* system, whereas a system that
responds to each event individually would be referred to as an *Edge Based* system.
{% endpanel %}
{% endpanel %}
## Overview of Kubernetes Resource APIs
### Pods
Containers are run in [*Pods*](https://kubernetes.io/docs/concepts/workloads/pods/pod-overview/) which are
scheduled to run on *Nodes* (i.e. worker machines) in a cluster.
Pods run a *single replica* of an Application and provide:
- Compute Resources (cpu, memory, disk)
- Environment Variables
- Readiness and Health Checking
- Network (IP address shared by containers in the Pod)
- Mounting Shared Configuration and Secrets
- Mounting Storage Volumes
- Initialization
{% panel style="warning", title="Multi Container Pods" %}
Multiple replicas of an Application should be created using a Workload API to manage
creation and deletion of Pod replicas using a PodTemplate.
In some cases a Pod may contain multiple Containers forming a single instance of an Application. These
containers may coordinate with one another through shared network (IP) and storage.
{% endpanel %}
### Workloads
Pods are typically managed by higher level abstractions that handle concerns such as
replication, identity, persistent storage, custom scheduling, rolling updates, etc.
The most common out-of-the-box Workload APIs (manage Pods) are:
- [Deployments](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) (Stateless Applications)
- replication + rollouts
- [StatefulSets](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/) (Stateful Applications)
- replication + rollouts + persistent storage + identity
- [Jobs](https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/) (Batch Work)
- run to completion
- [CronJobs](https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/) (Scheduled Batch Work)
- scheduled run to completion
- [DaemonSets](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/) (Per-Machine)
- per-Node scheduling
{% panel style="success", title="API Abstraction Layers" %}
High-level Workload APIs may manage lower-level Workload APIs instead of directly managing Pods
(e.g. Deployments manage ReplicaSets).
{% endpanel %}
### Service Discovery and Load Balancing
Service discovery and Load Balancing may be managed by a *Service* object. Services provide a single
virtual IP address and dns name load balanced to a collection of Pods matching Labels.
{% panel style="info", title="Internal vs External Services" %}
- [Services Resources](https://kubernetes.io/docs/concepts/services-networking/service/)
(L4) may expose Pods internally within a cluster or externally through an HA proxy.
- [Ingress Resources](https://kubernetes.io/docs/concepts/services-networking/ingress/) (L7)
may expose URI endpoints and route them to Services.
{% endpanel %}
### Configuration and Secrets
Shared Configuration and Secret data may be provided by ConfigMaps and Secrets. This allows
Environment Variables, Command Line Arguments and Files to be loosely injected into
the Pods and Containers that consume them.
{% panel style="info", title="ConfigMaps vs Secrets" %}
- [ConfigMaps](https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/)
are for providing non-sensitive data to Pods.
- [Secrets](https://kubernetes.io/docs/concepts/configuration/secret/)
are for providing sensitive data to Pods.
{% endpanel %}