7d90aeb906dfc9d60c7b245723719f258144b5ef
[dcaegen2/deployments.git] / cm-container / README.md
1 # Cloudify Manager Container Builder
2 ## Purpose
3 The artifacts in this directory build a Docker image based on the
4 public image from Cloudify (`cloudifyplatform/community`).  The
5 image has the Cloudify Manager software from the base image
6 and adds our types files.  It edits `/etc/cloudify/config.yaml`
7 to configure the import resolver to use our local type files instead
8 of fetching them over the Internet.   It adds
9 Cloudify 3.4 type files that are still used in some plugins
10 and blueprints.  Finally, it sets up the `/opt/onap` mount point
11 for our config files.
12
13 ## Running the Container
14 The container is intended to be launched via a Helm chart as part
15 of the ONAP deployment process, guided by OOM. It can be run directly
16 into a native Docker environment, using:
17 ```
18 docker run --name cfy-mgr -d --restart unless-stopped \
19    -v /sys/fs/cgroup:/sys/fs/cgroup:ro \
20    -p <some_external_port>:80 \
21    --tmpfs /run \
22    --tmpfs /run/lock \
23    --security-opt seccomp:unconfined
24    --cap-add SYS_ADMIN \
25    -v <path_to_kubeconfig_file>:/etc/cloudify/.kube/config
26    -v <path_to_config_file>:/opt/onap/config.txt
27    <image_name>
28 ```
29 In a Kubernetes environment, we expect that the <path_to_kubeconfile_file> and the
30 <path_to_config_file> mounts would be Kubernetes ConfigMaps.
31
32 We also expect that in a Kubernetes environment the external port mapping would not be
33 needed.
34
35 ## Persistent Storage
36 In an ONAP deployment driven by OOM, Cloudify Manager will store data related to its state
37 in a Kubernetes PersistentVolume.  If the Cloudify Manager pod is destroyed and recreated,
38 the new instance will have all of the state information from the previous run.
39
40 To set up persistent, we replace the command run by the container (`CMD` in the Dockerfile) with
41 our own script `start-persistent.sh`.  This script checks to see if a persistent volume has been
42 mounted in a well-known place (`/cfy-persist` in the container's file system).  If so, the script
43 then checks to see if the persistent volume has been populated with data.  There are two possibilities:
44 1. The persistent volume hasn't been populated, indicating that this is the first time Cloudify Manager is
45 being run in the current environment.  In this case, the script copies state data from several directories in
46 the container file system into directories in the persistent volume.  This is data (such as database schemas for
47 Cloudify Manager's internal postgres instance) that was generated when the original Cloudify Manager image was
48 created by Cloudify.
49 2. The persistent volume has been populated, indicating that this is not the first time Cloudify Manager is being
50 run in the current environment.   The data in the persistent volume reflects the state that Cloudify Manager was in
51 when it exited at some point in the past.   There's no need to copy data in this case.
52 In either case, the script will create symbolic links from the original data directories to the corresponding directories
53 in the persistent store.
54
55 If there is no persistent volume mounted, the script does nothing to set up persistent data, and the container will have
56 no persistent storage.
57
58 The last command in the script is the command from the original Cloudify version of the Cloudify Manager image. It runs `/sbin/init`,
59 which then brings up the many other processes needed for a working instance of Cloudify Manager.
60
61 ## The `setup-secret.sh` script
62 When Kubernetes starts a container, it mounts a directory containing the credentials that the container needs to access the Kubernetes API on the local Kubernetes cluster.  The mountpoint is `/var/run/secrets/kubernetes.io/serviceaccount`.   Something about the way that Cloudify Manager is started (possibly because `/sbin/init` is run) causes this mountpoint to be hidden.   `setup-secret.sh` will recreated the directory if it's not present and symbolically link it to a copy of the credentials mounted at `/secret` in the container file system.  This gives Cloudify Manager the credentials that the Kubernetes plugin needs to deploy Kubernetes-based DCAE components.
63
64 `setup-secret.sh` needs to run after '/sbin/init'.  The Dockerfile installs it in the `rc.local` script that runs at startup.
65
66 ## Cleaning up Kubernetes components deployed by Cloudify Manager
67 Using the `helm undeploy` (or `helm delete`) command will destroy the Kubernetes components deployed via helm.  In an ONAP deployment
68 driven by OOM, this includes destroying Cloudify Manager.  helm will *not* delete Kubernetes components deployed by Cloudify Manager.
69 This includes components ("microservices") deployed as part of the ONAP installation process by the DCAE bootstrap container as well as
70 components deployed after the initial installation using CLAMP.   Removing *all* of DCAE, including any components deployed by Cloudify
71 Manager, requires running a command before running the `helm undeploy` or `helm delete` command.
72
73 ```kubectl -n _namespace_ exec _cloudify_manager_pod_ /scripts/dcae-cleanup.sh```
74 where _namespace_ is the namespace in which ONAP was deployed and _cloudify_manager_pod_ is the ID of the pod running Cloudify Manager.
75
76 For example:
77 ```
78 $ kubectl -n onap exec dev-dcaegen2-dcae-cloudify-manager-bf885f5bd-hm97x /scripts/dcae-cleanup.sh
79 + set +e
80 ++ grep admin_password: /etc/cloudify/config.yaml
81 ++ cut -d : -f2
82 ++ tr -d ' '
83 + CMPASS=admin
84 + TYPENAMES='[\"dcae.nodes.ContainerizedServiceComponent\",\"dcae.nodes.ContainerizedServiceComponentUsingDmaap\",\"dcae.nodes.ContainerizedPlatformComponent\",\"dcae.nodes.ContainerizedApplication\"]'
85 + xargs -I % sh -c 'cfy executions start -d %  -p '\''{'\''\"type_names\":[\"dcae.nodes.ContainerizedServiceComponent\",\"dcae.nodes.ContainerizedServiceComponentUsingDmaap\",\"dcae.nodes.ContainerizedPlatformComponent\",\"dcae.nodes.ContainerizedApplication\"],\"operation\":\"cloudify.interfaces.lifecycle.stop\"'\''}'\'' execute_operation'
86 + /bin/jq '.items[].id'
87 + curl -Ss --user admin:admin -H 'Tenant: default_tenant' 'localhost/api/v3.1/deployments?_include=id'
88 Executing workflow execute_operation on deployment pgaas_initdb [timeout=900 seconds]
89 2019-03-06 23:06:06.838  CFY <pgaas_initdb> Starting 'execute_operation' workflow execution
90 2019-03-06 23:06:07.518  CFY <pgaas_initdb> 'execute_operation' workflow execution succeeded
91 Finished executing workflow execute_operation on deployment pgaas_initdb
92 * Run 'cfy events list -e c88d5a0a-9699-4077-961b-749384b1e455' to retrieve the execution's events/logs
93 Executing workflow execute_operation on deployment hv-ves [timeout=900 seconds]
94 2019-03-06 23:06:14.928  CFY <hv-ves> Starting 'execute_operation' workflow execution
95 2019-03-06 23:06:15.535  CFY <hv-ves> [hv-ves_dlkit2] Starting operation cloudify.interfaces.lifecycle.stop
96 2019-03-06 23:06:15.535  CFY <hv-ves> [hv-ves_dlkit2.stop] Sending task 'k8splugin.stop_and_remove_container'
97 2019-03-06 23:06:16.554  CFY <hv-ves> [hv-ves_dlkit2.stop] Task started 'k8splugin.stop_and_remove_container'
98 2019-03-06 23:06:20.163  CFY <hv-ves> [hv-ves_dlkit2.stop] Task succeeded 'k8splugin.stop_and_remove_container'
99 2019-03-06 23:06:20.561  CFY <hv-ves> [hv-ves_dlkit2] Finished operation cloudify.interfaces.lifecycle.stop
100 2019-03-06 23:06:21.570  CFY <hv-ves> 'execute_operation' workflow execution succeeded
101 Finished executing workflow execute_operation on deployment hv-ves
102 * Run 'cfy events list -e b4ea6608-befd-421d-9851-94527deab372' to retrieve the execution's events/logs
103 Executing workflow execute_operation on deployment datafile-collector [timeout=900 seconds]
104 2019-03-06 23:06:27.471  CFY <datafile-collector> Starting 'execute_operation' workflow execution
105 2019-03-06 23:06:28.593  CFY <datafile-collector> [datafile-collector_j2b0r4] Starting operation cloudify.interfaces.lifecycle.stop
106 2019-03-06 23:06:28.593  CFY <datafile-collector> [datafile-collector_j2b0r4.stop] Sending task 'k8splugin.stop_and_remove_container'
107 2019-03-06 23:06:28.593  CFY <datafile-collector> [datafile-collector_j2b0r4.stop] Task started 'k8splugin.stop_and_remove_container'
108 2019-03-06 23:06:32.078  CFY <datafile-collector> [datafile-collector_j2b0r4.stop] Task succeeded 'k8splugin.stop_and_remove_container'
109 2019-03-06 23:06:32.609  CFY <datafile-collector> [datafile-collector_j2b0r4] Finished operation cloudify.interfaces.lifecycle.stop
110 2019-03-06 23:06:32.609  CFY <datafile-collector> 'execute_operation' workflow execution succeeded
111 Finished executing workflow execute_operation on deployment datafile-collector
112 * Run 'cfy events list -e 24749c7e-591f-4cac-b127-420b0932ef09' to retrieve the execution's events/logs
113 Executing workflow execute_operation on deployment ves [timeout=900 seconds]
114 ```
115 The exact content of the output will depend on what components have been deployed.  Note that in the example output
116 above, the `pgaas_initdb` node was visited, but no 'stop' operation was sent because `pgaas_initdb` is not a Kubernetes node.
117