From 489221b2a923fc1705367a2e48c0c42db35c065c Mon Sep 17 00:00:00 2001 From: marco Date: Fri, 12 Aug 2016 14:09:51 +0200 Subject: [PATCH] delete unused addon scripts Change-Id: Idec7ef7f7142164b4615d656dea144770d73df54 --- .../files/kube-addons/kube-addon-update.sh | 507 ------------------ .../files/kube-addons/kube-addons.service | 9 - kubernetes/files/kube-addons/kube-addons.sh | 226 -------- kubernetes/master/kube-addons.sls | 14 - 4 files changed, 756 deletions(-) delete mode 100644 kubernetes/files/kube-addons/kube-addon-update.sh delete mode 100644 kubernetes/files/kube-addons/kube-addons.service delete mode 100644 kubernetes/files/kube-addons/kube-addons.sh diff --git a/kubernetes/files/kube-addons/kube-addon-update.sh b/kubernetes/files/kube-addons/kube-addon-update.sh deleted file mode 100644 index 77534a1..0000000 --- a/kubernetes/files/kube-addons/kube-addon-update.sh +++ /dev/null @@ -1,507 +0,0 @@ -#!/bin/bash - -# Copyright 2015 The Kubernetes Authors All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# The business logic for whether a given object should be created -# was already enforced by salt, and /etc/kubernetes/addons is the -# managed result is of that. Start everything below that directory. - -# Parameters -# $1 path to add-ons - - -# LIMITATIONS -# 1. controllers are not updated unless their name is changed -# 3. Services will not be updated unless their name is changed, -# but for services we actually want updates without name change. -# 4. Json files are not handled at all. Currently addons must be -# in yaml files -# 5. exit code is probably not always correct (I haven't checked -# carefully if it works in 100% cases) -# 6. There are no unittests -# 8. Will not work if the total length of paths to addons is greater than -# bash can handle. Probably it is not a problem: ARG_MAX=2097152 on GCE. -# 9. Performance issue: yaml files are read many times in a single execution. - -# cosmetic improvements to be done -# 1. improve the log function; add timestamp, file name, etc. -# 2. logging doesn't work from files that print things out. -# 3. kubectl prints the output to stderr (the output should be captured and then -# logged) - - - -# global config -KUBECTL=${TEST_KUBECTL:-} # substitute for tests -KUBECTL=${KUBECTL:-${KUBECTL_BIN:-}} -KUBECTL=${KUBECTL:-/usr/local/bin/kubectl} -if [[ ! -x ${KUBECTL} ]]; then - echo "ERROR: kubectl command (${KUBECTL}) not found or is not executable" 1>&2 - exit 1 -fi - -# If an add-on definition is incorrect, or a definition has just disappeared -# from the local directory, the script will still keep on retrying. -# The script does not end until all retries are done, so -# one invalid manifest may block updates of other add-ons. -# Be careful how you set these parameters -NUM_TRIES=1 # will be updated based on input parameters -DELAY_AFTER_ERROR_SEC=${TEST_DELAY_AFTER_ERROR_SEC:=10} - - -# remember that you can't log from functions that print some output (because -# logs are also printed on stdout) -# $1 level -# $2 message -function log() { - # manage log levels manually here - - # add the timestamp if you find it useful - case $1 in - DB3 ) -# echo "$1: $2" - ;; - DB2 ) -# echo "$1: $2" - ;; - DBG ) -# echo "$1: $2" - ;; - INFO ) - echo "$1: $2" - ;; - WRN ) - echo "$1: $2" - ;; - ERR ) - echo "$1: $2" - ;; - * ) - echo "INVALID_LOG_LEVEL $1: $2" - ;; - esac -} - -#$1 yaml file path -function get-object-kind-from-file() { - # prints to stdout, so log cannot be used - #WARNING: only yaml is supported - cat $1 | python -c ''' -try: - import pipes,sys,yaml - y = yaml.load(sys.stdin) - labels = y["metadata"]["labels"] - if ("kubernetes.io/cluster-service", "true") not in labels.iteritems(): - # all add-ons must have the label "kubernetes.io/cluster-service". - # Otherwise we are ignoring them (the update will not work anyway) - print "ERROR" - else: - print y["kind"] -except Exception, ex: - print "ERROR" - ''' -} - -# $1 yaml file path -# returns a string of the form / (we call it nsnames) -function get-object-nsname-from-file() { - # prints to stdout, so log cannot be used - #WARNING: only yaml is supported - #addons that do not specify a namespace are assumed to be in "default". - cat $1 | python -c ''' -try: - import pipes,sys,yaml - y = yaml.load(sys.stdin) - labels = y["metadata"]["labels"] - if ("kubernetes.io/cluster-service", "true") not in labels.iteritems(): - # all add-ons must have the label "kubernetes.io/cluster-service". - # Otherwise we are ignoring them (the update will not work anyway) - print "ERROR" - else: - try: - print "%s/%s" % (y["metadata"]["namespace"], y["metadata"]["name"]) - except Exception, ex: - print "default/%s" % y["metadata"]["name"] -except Exception, ex: - print "ERROR" - ''' -} - -# $1 addon directory path -# $2 addon type (e.g. ReplicationController) -# echoes the string with paths to files containing addon for the given type -# works only for yaml files (!) (ignores json files) -function get-addon-paths-from-disk() { - # prints to stdout, so log cannot be used - local -r addon_dir=$1 - local -r obj_type=$2 - local kind - local file_path - for file_path in $(find ${addon_dir} -name \*.yaml); do - kind=$(get-object-kind-from-file ${file_path}) - # WARNING: assumption that the topmost indentation is zero (I'm not sure yaml allows for topmost indentation) - if [[ "${kind}" == "${obj_type}" ]]; then - echo ${file_path} - fi - done -} - -# waits for all subprocesses -# returns 0 if all of them were successful and 1 otherwise -function wait-for-jobs() { - local rv=0 - local pid - for pid in $(jobs -p); do - wait ${pid} - if [[ $? -ne 0 ]]; then - rv=1; - log ERR "error in pid ${pid}" - fi - log DB2 "pid ${pid} completed, current error code: ${rv}" - done - return ${rv} -} - - -function run-until-success() { - local -r command=$1 - local tries=$2 - local -r delay=$3 - local -r command_name=$1 - while [ ${tries} -gt 0 ]; do - log DBG "executing: '$command'" - # let's give the command as an argument to bash -c, so that we can use - # && and || inside the command itself - /bin/bash -c "${command}" && \ - log DB3 "== Successfully executed ${command_name} at $(date -Is) ==" && \ - return 0 - let tries=tries-1 - log INFO "== Failed to execute ${command_name} at $(date -Is). ${tries} tries remaining. ==" - sleep ${delay} - done - return 1 -} - -# $1 object type -# returns a list of / pairs (nsnames) -function get-addon-nsnames-from-server() { - local -r obj_type=$1 - "${KUBECTL}" get "${obj_type}" --all-namespaces -o go-template="{{range.items}}{{.metadata.namespace}}/{{.metadata.name}} {{end}}" --api-version=v1 -l kubernetes.io/cluster-service=true -} - -# returns the characters after the last separator (including) -# If the separator is empty or if it doesn't appear in the string, -# an empty string is printed -# $1 input string -# $2 separator (must be single character, or empty) -function get-suffix() { - # prints to stdout, so log cannot be used - local -r input_string=$1 - local -r separator=$2 - local suffix - - if [[ "${separator}" == "" ]]; then - echo "" - return - fi - - if [[ "${input_string}" == *"${separator}"* ]]; then - suffix=$(echo "${input_string}" | rev | cut -d "${separator}" -f1 | rev) - echo "${separator}${suffix}" - else - echo "" - fi -} - -# returns the characters up to the last '-' (without it) -# $1 input string -# $2 separator -function get-basename() { - # prints to stdout, so log cannot be used - local -r input_string=$1 - local -r separator=$2 - local suffix - suffix="$(get-suffix ${input_string} ${separator})" - # this will strip the suffix (if matches) - echo ${input_string%$suffix} -} - -function stop-object() { - local -r obj_type=$1 - local -r namespace=$2 - local -r obj_name=$3 - log INFO "Stopping ${obj_type} ${namespace}/${obj_name}" - - run-until-success "${KUBECTL} stop --namespace=${namespace} ${obj_type} ${obj_name}" ${NUM_TRIES} ${DELAY_AFTER_ERROR_SEC} -} - -function create-object() { - local -r obj_type=$1 - local -r file_path=$2 - - local nsname_from_file - nsname_from_file=$(get-object-nsname-from-file ${file_path}) - if [[ "${nsname_from_file}" == "ERROR" ]]; then - log INFO "Cannot read object name from ${file_path}. Ignoring" - return 1 - fi - IFS='/' read namespace obj_name <<< "${nsname_from_file}" - - log INFO "Creating new ${obj_type} from file ${file_path} in namespace ${namespace}, name: ${obj_name}" - # this will keep on failing if the ${file_path} disappeared in the meantime. - # Do not use too many retries. - run-until-success "${KUBECTL} create --namespace=${namespace} -f ${file_path}" ${NUM_TRIES} ${DELAY_AFTER_ERROR_SEC} -} - -function update-object() { - local -r obj_type=$1 - local -r namespace=$2 - local -r obj_name=$3 - local -r file_path=$4 - log INFO "updating the ${obj_type} ${namespace}/${obj_name} with the new definition ${file_path}" - stop-object ${obj_type} ${namespace} ${obj_name} - create-object ${obj_type} ${file_path} -} - -# deletes the objects from the server -# $1 object type -# $2 a list of object nsnames -function stop-objects() { - local -r obj_type=$1 - local -r obj_nsnames=$2 - local namespace - local obj_name - for nsname in ${obj_nsnames}; do - IFS='/' read namespace obj_name <<< "${nsname}" - stop-object ${obj_type} ${namespace} ${obj_name} & - done -} - -# creates objects from the given files -# $1 object type -# $2 a list of paths to definition files -function create-objects() { - local -r obj_type=$1 - local -r file_paths=$2 - local file_path - for file_path in ${file_paths}; do - # Remember that the file may have disappear by now - # But we don't want to check it here because - # such race condition may always happen after - # we check it. Let's have the race - # condition happen a bit more often so that - # we see that our tests pass anyway. - create-object ${obj_type} ${file_path} & - done -} - -# updates objects -# $1 object type -# $2 a list of update specifications -# each update specification is a ';' separated pair: ; -function update-objects() { - local -r obj_type=$1 # ignored - local -r update_spec=$2 - local objdesc - local nsname - local obj_name - local namespace - - for objdesc in ${update_spec}; do - IFS=';' read nsname file_path <<< "${objdesc}" - IFS='/' read namespace obj_name <<< "${nsname}" - - update-object ${obj_type} ${namespace} ${obj_name} ${file_path} & - done -} - -# Global variables set by function match-objects. -nsnames_for_delete="" # a list of object nsnames to be deleted -for_update="" # a list of pairs ; for objects that should be updated -nsnames_for_ignore="" # a list of object nsnames that will be ignored -new_files="" # a list of file paths that weren't matched by any existing objects (these objects must be created now) - - -# $1 path to files with objects -# $2 object type in the API (ReplicationController or Service) -# $3 name separator (single character or empty) -function match-objects() { - local -r addon_dir=$1 - local -r obj_type=$2 - local -r separator=$3 - - # output variables (globals) - nsnames_for_delete="" - for_update="" - nsnames_for_ignore="" - new_files="" - - addon_nsnames_on_server=$(get-addon-nsnames-from-server "${obj_type}") - addon_paths_in_files=$(get-addon-paths-from-disk "${addon_dir}" "${obj_type}") - - log DB2 "addon_nsnames_on_server=${addon_nsnames_on_server}" - log DB2 "addon_paths_in_files=${addon_paths_in_files}" - - local matched_files="" - - local basensname_on_server="" - local nsname_on_server="" - local suffix_on_server="" - local nsname_from_file="" - local suffix_from_file="" - local found=0 - local addon_path="" - - # objects that were moved between namespaces will have different nsname - # because the namespace is included. So they will be treated - # like different objects and not updated but deleted and created again - # (in the current version update is also delete+create, so it does not matter) - for nsname_on_server in ${addon_nsnames_on_server}; do - basensname_on_server=$(get-basename ${nsname_on_server} ${separator}) - suffix_on_server="$(get-suffix ${nsname_on_server} ${separator})" - - log DB3 "Found existing addon ${nsname_on_server}, basename=${basensname_on_server}" - - # check if the addon is present in the directory and decide - # what to do with it - # this is not optimal because we're reading the files over and over - # again. But for small number of addons it doesn't matter so much. - found=0 - for addon_path in ${addon_paths_in_files}; do - nsname_from_file=$(get-object-nsname-from-file ${addon_path}) - if [[ "${nsname_from_file}" == "ERROR" ]]; then - log INFO "Cannot read object name from ${addon_path}. Ignoring" - continue - else - log DB2 "Found object name '${nsname_from_file}' in file ${addon_path}" - fi - suffix_from_file="$(get-suffix ${nsname_from_file} ${separator})" - - log DB3 "matching: ${basensname_on_server}${suffix_from_file} == ${nsname_from_file}" - if [[ "${basensname_on_server}${suffix_from_file}" == "${nsname_from_file}" ]]; then - log DB3 "matched existing ${obj_type} ${nsname_on_server} to file ${addon_path}; suffix_on_server=${suffix_on_server}, suffix_from_file=${suffix_from_file}" - found=1 - matched_files="${matched_files} ${addon_path}" - if [[ "${suffix_on_server}" == "${suffix_from_file}" ]]; then - nsnames_for_ignore="${nsnames_for_ignore} ${nsname_from_file}" - else - for_update="${for_update} ${nsname_on_server};${addon_path}" - fi - break - fi - done - if [[ ${found} -eq 0 ]]; then - log DB2 "No definition file found for replication controller ${nsname_on_server}. Scheduling for deletion" - nsnames_for_delete="${nsnames_for_delete} ${nsname_on_server}" - fi - done - - log DB3 "matched_files=${matched_files}" - - - # note that if the addon file is invalid (or got removed after listing files - # but before we managed to match it) it will not be matched to any - # of the existing objects. So we will treat it as a new file - # and try to create its object. - for addon_path in ${addon_paths_in_files}; do - echo ${matched_files} | grep "${addon_path}" >/dev/null - if [[ $? -ne 0 ]]; then - new_files="${new_files} ${addon_path}" - fi - done -} - - - -function reconcile-objects() { - local -r addon_path=$1 - local -r obj_type=$2 - local -r separator=$3 # name separator - match-objects ${addon_path} ${obj_type} ${separator} - - log DBG "${obj_type}: nsnames_for_delete=${nsnames_for_delete}" - log DBG "${obj_type}: for_update=${for_update}" - log DBG "${obj_type}: nsnames_for_ignore=${nsnames_for_ignore}" - log DBG "${obj_type}: new_files=${new_files}" - - stop-objects "${obj_type}" "${nsnames_for_delete}" - # wait for jobs below is a protection against changing the basename - # of a replication controllerm without changing the selector. - # If we don't wait, the new rc may be created before the old one is deleted - # In such case the old one will wait for all its pods to be gone, but the pods - # are created by the new replication controller. - # passing --cascade=false could solve the problem, but we want - # all orphan pods to be deleted. - wait-for-jobs - stopResult=$? - - create-objects "${obj_type}" "${new_files}" - update-objects "${obj_type}" "${for_update}" - - local nsname - for nsname in ${nsnames_for_ignore}; do - log DB2 "The ${obj_type} ${nsname} is already up to date" - done - - wait-for-jobs - createUpdateResult=$? - - if [[ ${stopResult} -eq 0 ]] && [[ ${createUpdateResult} -eq 0 ]]; then - return 0 - else - return 1 - fi -} - -function update-addons() { - local -r addon_path=$1 - # be careful, reconcile-objects uses global variables - reconcile-objects ${addon_path} ReplicationController "-" & - - # We don't expect names to be versioned for the following kinds, so - # we match the entire name, ignoring version suffix. - # That's why we pass an empty string as the version separator. - # If the description differs on disk, the object should be recreated. - # This is not implemented in this version. - reconcile-objects ${addon_path} Service "" & - reconcile-objects ${addon_path} PersistentVolume "" & - reconcile-objects ${addon_path} PersistentVolumeClaim "" & - - wait-for-jobs - if [[ $? -eq 0 ]]; then - log INFO "== Kubernetes addon update completed successfully at $(date -Is) ==" - else - log WRN "== Kubernetes addon update completed with errors at $(date -Is) ==" - fi -} - -# input parameters: -# $1 input directory -# $2 retry period in seconds - the script will retry api-server errors for approximately -# this amound of time (it is not very precise), at interval equal $DELAY_AFTER_ERROR_SEC. -# - -if [[ $# -ne 2 ]]; then - echo "Illegal number of parameters. Usage $0 addon-dir [retry-period]" 1>&2 - exit 1 -fi - -NUM_TRIES=$(($2 / ${DELAY_AFTER_ERROR_SEC})) -if [[ ${NUM_TRIES} -le 0 ]]; then - NUM_TRIES=1 -fi - -addon_path=$1 -update-addons ${addon_path} \ No newline at end of file diff --git a/kubernetes/files/kube-addons/kube-addons.service b/kubernetes/files/kube-addons/kube-addons.service deleted file mode 100644 index 920f356..0000000 --- a/kubernetes/files/kube-addons/kube-addons.service +++ /dev/null @@ -1,9 +0,0 @@ -[Unit] -Description=Kubernetes Addon Object Manager -Documentation=https://github.com/GoogleCloudPlatform/kubernetes - -[Service] -ExecStart=/etc/kubernetes/kube-addons.sh - -[Install] -WantedBy=multi-user.target \ No newline at end of file diff --git a/kubernetes/files/kube-addons/kube-addons.sh b/kubernetes/files/kube-addons/kube-addons.sh deleted file mode 100644 index c1deea1..0000000 --- a/kubernetes/files/kube-addons/kube-addons.sh +++ /dev/null @@ -1,226 +0,0 @@ -#!/bin/bash - -# Copyright 2014 The Kubernetes Authors All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# The business logic for whether a given object should be created -# was already enforced by salt, and /etc/kubernetes/addons is the -# managed result is of that. Start everything below that directory. -KUBECTL=${KUBECTL_BIN:-/usr/local/bin/kubectl} - -ADDON_CHECK_INTERVAL_SEC=${TEST_ADDON_CHECK_INTERVAL_SEC:-600} - -SYSTEM_NAMESPACE=kube-system -token_dir=${TOKEN_DIR:-/srv/kubernetes} - -function create-kubeconfig-secret() { - local -r token=$1 - local -r username=$2 - local -r server=$3 - local -r safe_username=$(tr -s ':_' '--' <<< "${username}") - - # Make a kubeconfig file with the token. - if [[ ! -z "${CA_CERT:-}" ]]; then - # If the CA cert is available, put it into the secret rather than using - # insecure-skip-tls-verify. - read -r -d '' kubeconfig </dev/null - rc=$? - if [[ "$rc" == 124 ]]; then - restart_docker=true - elif [[ "$rc" != 0 ]]; then - success=false - fi - done - if [[ "$success" == "true" ]]; then break; fi - if [[ "$restart_docker" == "true" ]]; then service docker restart; fi - sleep 15 - done -} - -# The business logic for whether a given object should be created -# was already enforced by salt, and /etc/kubernetes/addons is the -# managed result is of that. Start everything below that directory. -echo "== Kubernetes addon manager started at $(date -Is) with ADDON_CHECK_INTERVAL_SEC=${ADDON_CHECK_INTERVAL_SEC} ==" - -# Load the kube-env, which has all the environment variables we care -# about, in a flat yaml format. -kube_env_yaml="/var/cache/kubernetes-install/kube_env.yaml" -if [ ! -e "${kubelet_kubeconfig_file}" ]; then - eval $(python -c ''' -import pipes,sys,yaml - -for k,v in yaml.load(sys.stdin).iteritems(): - print "readonly {var}={value}".format(var = k, value = pipes.quote(str(v))) -''' < "${kube_env_yaml}") -fi - -# Load any images that we may need -load-docker-images /srv/salt/kube-addons-images - -# Create the namespace that will be used to host the cluster-level add-ons. -start_addon /etc/kubernetes/addons/namespace.yaml 100 10 "" & - -# Wait for the default service account to be created in the kube-system namespace. -token_found="" -while [ -z "${token_found}" ]; do - sleep .5 - token_found=$(${KUBECTL} get --namespace="${SYSTEM_NAMESPACE}" serviceaccount default -o go-template="{{with index .secrets 0}}{{.name}}{{end}}" || true) -done - -echo "== default service account in the ${SYSTEM_NAMESPACE} namespace has token ${token_found} ==" - -# Generate secrets for "internal service accounts". -# TODO(etune): move to a completely yaml/object based -# workflow so that service accounts can be created -# at the same time as the services that use them. -# NOTE: needs to run as root to read this file. -# Read each line in the csv file of tokens. -# Expect errors when the script is started again. -# NOTE: secrets are created asynchronously, in background. -while read line; do - # Split each line into the token and username. - IFS=',' read -a parts <<< "${line}" - token=${parts[0]} - username=${parts[1]} - # DNS is special, since it's necessary for cluster bootstrapping. - if [[ "${username}" == "system:dns" ]] && [[ ! -z "${KUBERNETES_MASTER_NAME:-}" ]]; then - create-kubeconfig-secret "${token}" "${username}" "https://${KUBERNETES_MASTER_NAME}" - else - # Set the server to https://kubernetes. Pods/components that - # do not have DNS available will have to override the server. - create-kubeconfig-secret "${token}" "${username}" "https://kubernetes.default" - fi -done < "${token_dir}/known_tokens.csv" - -# Create admission_control objects if defined before any other addon services. If the limits -# are defined in a namespace other than default, we should still create the limits for the -# default namespace. -for obj in $(find /etc/kubernetes/admission-controls \( -name \*.yaml -o -name \*.json \)); do - start_addon "${obj}" 100 10 default & - echo "++ obj ${obj} is created ++" -done - -# Check if the configuration has changed recently - in case the user -# created/updated/deleted the files on the master. -while true; do - start_sec=$(date +"%s") - #kube-addon-update.sh must be deployed in the same directory as this file - `dirname $0`/kube-addon-update.sh /etc/kubernetes/addons ${ADDON_CHECK_INTERVAL_SEC} - end_sec=$(date +"%s") - len_sec=$((${end_sec}-${start_sec})) - # subtract the time passed from the sleep time - if [[ ${len_sec} -lt ${ADDON_CHECK_INTERVAL_SEC} ]]; then - sleep_time=$((${ADDON_CHECK_INTERVAL_SEC}-${len_sec})) - sleep ${sleep_time} - fi -done \ No newline at end of file diff --git a/kubernetes/master/kube-addons.sls b/kubernetes/master/kube-addons.sls index c251861..b5e04ff 100644 --- a/kubernetes/master/kube-addons.sls +++ b/kubernetes/master/kube-addons.sls @@ -155,18 +155,4 @@ addon-dir-create: {% endif %} -/etc/kubernetes/kube-addons.sh: - file.managed: - - source: salt://kubernetes/files/kube-addons/kube-addons.sh - - user: root - - group: root - - mode: 755 - -/etc/kubernetes/kube-addon-update.sh: - file.managed: - - source: salt://kubernetes/files/kube-addons/kube-addon-update.sh - - user: root - - group: root - - mode: 755 - {% endif %} \ No newline at end of file