[root@master ~]# systemctl stop firewalld
[root@master ~]# systemctl disable firewalld
Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
Removed symlink /etc/systemd/system/basic.target.wants/firewalld.service.
[root@master ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1460 qdisc pfifo_fast state UP qlen 1000
link/ether 42:01:0a:80:00:02 brd ff:ff:ff:ff:ff:ff
inet 10.128.0.2/32 brd 10.128.0.2 scope global dynamic eth0
valid_lft 86172sec preferred_lft 86172sec
[root@master ~]# setenforce 0
[root@master ~]# yum update -y
[root@master ~]# yum install ebtables ethtool -y
[root@master ~]# yum install -y docker
[root@master ~]# docker version
Client:
Version: 1.12.6
API version: 1.24
Package version: docker-1.12.6-55.gitc4618fb.el7.centos.x86_64
Go version: go1.8.3
Git commit: c4618fb/1.12.6
Built: Thu Sep 21 22:33:52 2017
OS/Arch: linux/amd64
Cannot connect to the Docker daemon. Is the docker daemon running on this host?
[root@master ~]# systemctl enable docker && systemctl start docker
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.
[root@master ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1460 qdisc pfifo_fast state UP qlen 1000
link/ether 42:01:0a:80:00:02 brd ff:ff:ff:ff:ff:ff
inet 10.128.0.2/32 brd 10.128.0.2 scope global dynamic eth0
valid_lft 85921sec preferred_lft 85921sec
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN
link/ether 02:42:e8:a2:9f:6e brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 scope global docker0
valid_lft forever preferred_lft forever
[root@master ~]# cat < /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg
https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF
[root@master ~]# yum install -y kubelet kubeadm kubectl
[root@master ~]# systemctl enable kubelet && systemctl start kubelet
Created symlink from /etc/systemd/system/multi-user.target.wants/kubelet.service to /etc/systemd/system/kubelet.service.
[root@master ~]# netstat -tlpn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 954/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1139/master
tcp6 0 0 :::22 :::* LISTEN 954/sshd
tcp6 0 0 ::1:25 :::* LISTEN 1139/master
[root@master ~]# kubeadm init
[kubeadm] WARNING: kubeadm is in beta, please do not use it for production clusters.
[init] Using Kubernetes version: v1.8.0
[init] Using Authorization modes: [Node RBAC]
[preflight] Running pre-flight checks
[preflight] Some fatal errors occurred:
/var/lib/kubelet is not empty
[preflight] If you know what you are doing, you can skip pre-flight checks with `–skip-preflight-checks`
[root@master ~]# kubeadm reset
[preflight] Running pre-flight checks
[reset] Stopping the kubelet service
[reset] Unmounting mounted directories in “/var/lib/kubelet”
[reset] Removing kubernetes-managed containers
[reset] No etcd manifest found in “/etc/kubernetes/manifests/etcd.yaml”, assuming external etcd.
[reset] Deleting contents of stateful directories: [/var/lib/kubelet /etc/cni/net.d /var/lib/dockershim /var/run/kubernetes]
[reset] Deleting contents of config directories: [/etc/kubernetes/manifests /etc/kubernetes/pki]
[reset] Deleting files: [/etc/kubernetes/admin.conf /etc/kubernetes/kubelet.conf /etc/kubernetes/controller-manager.conf /etc/kubernetes/scheduler.conf]
[root@master ~]# rm -rf /var/lib/kubelet/
[root@master ~]# kubeadm init
[kubeadm] WARNING: kubeadm is in beta, please do not use it for production clusters.
[init] Using Kubernetes version: v1.8.0
[init] Using Authorization modes: [Node RBAC]
[preflight] Running pre-flight checks
[preflight] Starting the kubelet service
[kubeadm] WARNING: starting in 1.8, tokens expire after 24 hours by default (if you require a non-expiring token use –token-ttl 0)
[certificates] Generated ca certificate and key.
[certificates] Generated apiserver certificate and key.
[certificates] apiserver serving cert is signed for DNS names [master kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 10.128.0.2]
[certificates] Generated apiserver-kubelet-client certificate and key.
[certificates] Generated sa key and public key.
[certificates] Generated front-proxy-ca certificate and key.
[certificates] Generated front-proxy-client certificate and key.
[certificates] Valid certificates and keys now exist in “/etc/kubernetes/pki”
[kubeconfig] Wrote KubeConfig file to disk: “admin.conf”
[kubeconfig] Wrote KubeConfig file to disk: “kubelet.conf”
[kubeconfig] Wrote KubeConfig file to disk: “controller-manager.conf”
[kubeconfig] Wrote KubeConfig file to disk: “scheduler.conf”
[controlplane] Wrote Static Pod manifest for component kube-apiserver to “/etc/kubernetes/manifests/kube-apiserver.yaml”
[controlplane] Wrote Static Pod manifest for component kube-controller-manager to “/etc/kubernetes/manifests/kube-controller-manager.yaml”
[controlplane] Wrote Static Pod manifest for component kube-scheduler to “/etc/kubernetes/manifests/kube-scheduler.yaml”
[etcd] Wrote Static Pod manifest for a local etcd instance to “/etc/kubernetes/manifests/etcd.yaml”
[init] Waiting for the kubelet to boot up the control plane as Static Pods from directory “/etc/kubernetes/manifests”
[init] This often takes around a minute; or longer if the control plane images have to be pulled.
[apiclient] All control plane components are healthy after 48.506830 seconds
[uploadconfig] Storing the configuration used in ConfigMap “kubeadm-config” in the “kube-system” Namespace
[markmaster] Will mark node master as master by adding a label and a taint
[markmaster] Master master tainted and labelled with key/value: node-role.kubernetes.io/master=””
[bootstraptoken] Using token: 381c86.c45494795fdc5c83
[bootstraptoken] Configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstraptoken] Configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstraptoken] Creating the “cluster-info” ConfigMap in the “kube-public” namespace
[addons] Applied essential addon: kube-dns
[addons] Applied essential addon: kube-proxy
Your Kubernetes master has initialized successfully!
To start using your cluster, you need to run (as a regular user):
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
You should now deploy a pod network to the cluster.
Run “kubectl apply -f [podnetwork].yaml” with one of the options listed at:
http://kubernetes.io/docs/admin/addons/
You can now join any number of machines by running the following on each node
as root:
kubeadm join –token 381c86.c45494795fdc5c83 10.128.0.2:6443 –discovery-token-ca-cert-hash sha256:4b2830fca6829c74be83987d6b4b746770356ed8f08485ab56327c98d4ace8bd
[root@master ~]# su – mohammedrafi
Last login: Sat Oct 7 12:25:05 UTC 2017 from 183.82.220.31 on pts/0
[mohammedrafi@master ~]$ mkdir -p $HOME/.kube
[mohammedrafi@master ~]$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
[mohammedrafi@master ~]$ sudo chown $(id -u):$(id -g) $HOME/.kube/config
[mohammedrafi@master ~]$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready master 2m v1.8.0
[mohammedrafi@master ~]$ kubectl get pods
No resources found.
[mohammedrafi@master ~]$ kubectl get pods –all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system etcd-master 1/1 Running 0 1m
kube-system kube-apiserver-master 1/1 Running 0 1m
kube-system kube-controller-manager-master 1/1 Running 0 1m
kube-system kube-dns-545bc4bfd4-pfwgk 0/3 Pending 0 2m
kube-system kube-proxy-pv75h 1/1 Running 0 2m
kube-system kube-scheduler-master 1/1 Running 0 1m
[mohammedrafi@master ~]$ wget https://git.io/weave-kube-1.6
[mohammedrafi@master ~]$ cat weave-kube-1.6
apiVersion: v1
kind: List
items:
– apiVersion: v1
kind: ServiceAccount
metadata:
name: weave-net
labels:
name: weave-net
namespace: kube-system
– apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: weave-net
labels:
name: weave-net
rules:
– apiGroups:
– ”
resources:
– pods
– namespaces
– nodes
verbs:
– get
– list
– watch
– apiGroups:
– extensions
resources:
– networkpolicies
verbs:
– get
– list
– watch
– apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: weave-net
labels:
name: weave-net
roleRef:
kind: ClusterRole
name: weave-net
apiGroup: rbac.authorization.k8s.io
subjects:
– kind: ServiceAccount
name: weave-net
namespace: kube-system
– apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: weave-net
labels:
name: weave-net
namespace: kube-system
spec:
template:
metadata:
labels:
name: weave-net
spec:
containers:
– name: weave
command:
– /home/weave/launch.sh
env:
– name: HOSTNAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: spec.nodeName
image: ‘weaveworks/weave-kube:2.0.4’
livenessProbe:
httpGet:
host: 127.0.0.1
path: /status
port: 6784
initialDelaySeconds: 30
resources:
requests:
cpu: 10m
securityContext:
privileged: true
volumeMounts:
– name: weavedb
mountPath: /weavedb
– name: cni-bin
mountPath: /host/opt
– name: cni-bin2
mountPath: /host/home
– name: cni-conf
mountPath: /host/etc
– name: dbus
mountPath: /host/var/lib/dbus
– name: lib-modules
mountPath: /lib/modules
– name: weave-npc
env:
– name: HOSTNAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: spec.nodeName
image: ‘weaveworks/weave-npc:2.0.4’
resources:
requests:
cpu: 10m
securityContext:
privileged: true
hostNetwork: true
hostPID: true
restartPolicy: Always
securityContext:
seLinuxOptions: {}
serviceAccountName: weave-net
tolerations:
– effect: NoSchedule
operator: Exists
volumes:
– name: weavedb
hostPath:
path: /var/lib/weave
– name: cni-bin
hostPath:
path: /opt
– name: cni-bin2
hostPath:
path: /home
– name: cni-conf
hostPath:
path: /etc
– name: dbus
hostPath:
path: /var/lib/dbus
– name: lib-modules
hostPath:
path: /lib/modules
updateStrategy:
type: RollingUpdate
[mohammedrafi@master ~]$ kubectl apply -f weave-kube-1.6
serviceaccount “weave-net” created
clusterrole “weave-net” created
clusterrolebinding “weave-net” created
daemonset “weave-net” created
[mohammedrafi@master ~]$ kubectl get pods –all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system etcd-master 1/1 Running 0 41s
kube-system kube-apiserver-master 1/1 Running 0 41s
kube-system kube-controller-manager-master 1/1 Running 0 41s
kube-system kube-dns-545bc4bfd4-pfwgk 3/3 Running 0 9m
kube-system kube-proxy-pv75h 1/1 Running 0 9m
kube-system kube-scheduler-master 1/1 Running 0 41s
kube-system weave-net-xkmvq 2/2 Running 0 56s
[mohammedrafi@master ~]$ sudo -i
[root@master ~]# netstat -tlpn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.1:10251 0.0.0.0:* LISTEN 13073/kube-schedule
tcp 0 0 127.0.0.1:2379 0.0.0.0:* LISTEN 12978/etcd
tcp 0 0 127.0.0.1:2380 0.0.0.0:* LISTEN 12978/etcd
tcp 0 0 127.0.0.1:10252 0.0.0.0:* LISTEN 12848/kube-controll
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 954/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1139/master
tcp 0 0 0.0.0.0:6783 0.0.0.0:* LISTEN 14191/weaver
tcp 0 0 127.0.0.1:6784 0.0.0.0:* LISTEN 14191/weaver
tcp 0 0 127.0.0.1:10248 0.0.0.0:* LISTEN 12346/kubelet
tcp 0 0 127.0.0.1:10249 0.0.0.0:* LISTEN 13374/kube-proxy
tcp6 0 0 :::6443 :::* LISTEN 13166/kube-apiserve
tcp6 0 0 :::10255 :::* LISTEN 12346/kubelet
tcp6 0 0 :::10256 :::* LISTEN 13374/kube-proxy
tcp6 0 0 :::22 :::* LISTEN 954/sshd
tcp6 0 0 ::1:25 :::* LISTEN 1139/master
tcp6 0 0 :::6781 :::* LISTEN 14489/weave-npc
tcp6 0 0 :::6782 :::* LISTEN 14191/weaver
tcp6 0 0 :::10250 :::* LISTEN 12346/kubelet
#################### Minion-1 #####################
[mohammedrafi@node1 ~]$ sudo -i
[root@node1 ~]#
[root@node1 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1460 qdisc pfifo_fast state UP qlen 1000
link/ether 42:01:0a:80:00:03 brd ff:ff:ff:ff:ff:ff
inet 10.128.0.3/32 brd 10.128.0.3 scope global dynamic eth0
valid_lft 86346sec preferred_lft 86346sec
[root@node1 ~]# setenforce 0
[root@node1 ~]# systemctl disable firewalld
Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
Removed symlink /etc/systemd/system/basic.target.wants/firewalld.service.
[root@node1 ~]# systemctl stop firewalld
[root@node1 ~]# yum install -y docker
[root@node1 ~]# cat < /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg
https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF
[root@node1 ~]# yum install -y kubelet kubeadm kubectl
[root@node1 ~]# systemctl enable kubelet && systemctl start kubelet
Created symlink from /etc/systemd/system/multi-user.target.wants/kubelet.service to /etc/systemd/system/kubelet.service.
[root@node1 ~]# netstat -tlpn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 948/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1146/master
tcp 0 0 0.0.0.0:6783 0.0.0.0:* LISTEN 2923/weaver
tcp 0 0 127.0.0.1:6784 0.0.0.0:* LISTEN 2923/weaver
tcp 0 0 127.0.0.1:10248 0.0.0.0:* LISTEN 1979/kubelet
tcp 0 0 127.0.0.1:10249 0.0.0.0:* LISTEN 2576/kube-proxy
tcp6 0 0 :::10255 :::* LISTEN 1979/kubelet
tcp6 0 0 :::10256 :::* LISTEN 2576/kube-proxy
tcp6 0 0 :::22 :::* LISTEN 948/sshd
tcp6 0 0 ::1:25 :::* LISTEN 1146/master
tcp6 0 0 :::6781 :::* LISTEN 2760/weave-npc
tcp6 0 0 :::6782 :::* LISTEN 2923/weaver
tcp6 0 0 :::10250 :::* LISTEN 1979/kubelet
[root@node1 ~]# kubeadm join –token 381c86.c45494795fdc5c83 10.128.0.2:6443 –discovery-token-ca-cert-hash sha256:4b2830fca6829c74be83987d6b4b746770356ed8f08485ab56327c98d4ace8bd
[kubeadm] WARNING: kubeadm is in beta, please do not use it for production clusters.
[preflight] Running pre-flight checks
[preflight] The system verification failed. Printing the output from the verification:
OS: Linux
KERNEL_VERSION: 3.10.0-693.2.2.el7.x86_64
CONFIG_NAMESPACES: enabled
CONFIG_NET_NS: enabled
CONFIG_PID_NS: enabled
CONFIG_IPC_NS: enabled
CONFIG_UTS_NS: enabled
CONFIG_CGROUPS: enabled
CONFIG_CGROUP_CPUACCT: enabled
CONFIG_CGROUP_DEVICE: enabled
CONFIG_CGROUP_FREEZER: enabled
CONFIG_CGROUP_SCHED: enabled
CONFIG_CPUSETS: enabled
CONFIG_MEMCG: enabled
CONFIG_INET: enabled
CONFIG_EXT4_FS: enabled (as module)
CONFIG_PROC_FS: enabled
CONFIG_NETFILTER_XT_TARGET_REDIRECT: enabled (as module)
CONFIG_NETFILTER_XT_MATCH_COMMENT: enabled (as module)
CONFIG_OVERLAY_FS: enabled (as module)
CONFIG_AUFS_FS: not set – Required for aufs.
CONFIG_BLK_DEV_DM: enabled (as module)
CGROUPS_CPU: enabled
CGROUPS_CPUACCT: enabled
CGROUPS_CPUSET: enabled
CGROUPS_DEVICES: enabled
CGROUPS_FREEZER: enabled
CGROUPS_MEMORY: enabled
[preflight] WARNING: docker service is not enabled, please run ‘systemctl enable docker.service’
[preflight] Some fatal errors occurred:
failed to get docker info: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
docker service is not active, please run ‘systemctl start docker.service’
/var/lib/kubelet is not empty
/proc/sys/net/bridge/bridge-nf-call-iptables does not exist
[preflight] If you know what you are doing, you can skip pre-flight checks with `–skip-preflight-checks`
[root@node1 ~]# systemctl start docker
[root@node1 ~]# systemctl enable docker
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.
[mohammedrafi@node1 ~]$ telnet 10.128.0.2 6443
Trying 10.128.0.2…
Connected to 10.128.0.2.
Escape character is ‘^]’.
^CConnection closed by foreign host.
[root@node1 ~]# kubeadm join –token 381c86.c45494795fdc5c83 10.128.0.2:6443 –discovery-token-ca-cert-hash sha256:4b2830fca6829c74be83987d6b4b746770356ed8f08485ab56327c98d4ace8bd
[kubeadm] WARNING: kubeadm is in beta, please do not use it for production clusters.
[preflight] Running pre-flight checks
[preflight] Starting the kubelet service
[discovery] Trying to connect to API Server “10.128.0.2:6443”
[discovery] Created cluster-info discovery client, requesting info from “https://10.128.0.2:6443”
[discovery] Requesting info from “https://10.128.0.2:6443” again to validate TLS against the pinned public key
[discovery] Cluster info signature and contents are valid and TLS certificate validates against pinned roots, will use API Server “10.128.0.2:6443”
[discovery] Successfully established connection with API Server “10.128.0.2:6443”
[bootstrap] Detected server version: v1.8.0
[bootstrap] The server supports the Certificates API (certificates.k8s.io/v1beta1)
Node join complete:
* Certificate signing request sent to master and response
received.
* Kubelet informed of new secure connection details.
Run ‘kubectl get nodes’ on the master to see this machine join.
#################### Master #####################
[mohammedrafi@master ~]$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready master 26m v1.8.0
node1 NotReady 30s v1.8.0
[mohammedrafi@master ~]$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready master 27m v1.8.0
node1 Ready 56s v1.8.0
[root@master ~]# kubeadm
kubeadm: easily bootstrap a secure Kubernetes cluster.
┌──────────────────────────────────────────────────────────┐
│ KUBEADM IS BETA, DO NOT USE IT FOR PRODUCTION CLUSTERS! │
│ │
│ But, please try it out! Give us feedback at: │
│ https://github.com/kubernetes/kubeadm/issues │
│ and at-mention @kubernetes/sig-cluster-lifecycle-bugs │
│ or @kubernetes/sig-cluster-lifecycle-feature-requests │
└──────────────────────────────────────────────────────────┘
Example usage:
Create a two-machine cluster with one master (which controls the cluster),
and one node (where your workloads, like Pods and Deployments run).
┌──────────────────────────────────────────────────────────┐
│ On the first machine │
├──────────────────────────────────────────────────────────┤
│ master# kubeadm init │
└──────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────┐
│ On the second machine │
├──────────────────────────────────────────────────────────┤
│ node# kubeadm join <arguments-returned-from-init> │
└──────────────────────────────────────────────────────────┘
You can then repeat the second step on as many other machines as you like.
Usage:
kubeadm [command]
Available Commands:
alpha Experimental sub-commands not yet fully functional.
completion Output shell completion code for the specified shell (bash or zsh)
config Manage configuration for a kubeadm cluster persisted in a ConfigMap in the cluster.
init Run this in order to set up the Kubernetes master
join Run this on any machine you wish to join an existing cluster
reset Run this to revert any changes made to this host by ‘kubeadm init’ or ‘kubeadm join’.
token Manage bootstrap tokens.
upgrade Upgrade your cluster smoothly to a newer version with this command.
version Print the version of kubeadm
Flags:
-h, –help help for kubeadm
Use “kubeadm [command] –help” for more information about a command.
