Build smart into your docker images


We have been running mysql 5.7 on OpenShift with RedHat provisioned images.  To make it work is easy, but to make it work correctly is a bit harder. One example is that how to setup the innodb_buffer_pool_size (one of the most important parameters of mysql)? When you build the image you don’t know how much memory the containers will have. Different environments have different settings. So it has to be dynamic. My initial thought was to pass it through the environment variable when creating the containers. The drawback is obvious – what if the users don’t know what parameter they can pass? or if memory limit is configured against the container.

After some researches, it turns out that RedHat has already taken care of it by embedding some smart scripts in the image. So the script can setup those parameters accordingly when container is created.

The logic is that some of the memory-related parameters have two default values. The fixed value is used when a container does not have memory limits assigned. The other value is calculated dynamically during a container’s startup based on available memory.

  # Export memory limit variables and calculate limits
  local export_vars=$(cgroup-limits) && export $export_vars || exit 1
  if [ -n "${NO_MEMORY_LIMIT:-}" -o -z "${MEMORY_LIMIT_IN_BYTES:-}" ]; then
    export MYSQL_KEY_BUFFER_SIZE=${MYSQL_KEY_BUFFER_SIZE:-32M}
    export MYSQL_READ_BUFFER_SIZE=${MYSQL_READ_BUFFER_SIZE:-8M}
    export MYSQL_INNODB_BUFFER_POOL_SIZE=${MYSQL_INNODB_BUFFER_POOL_SIZE:-32M}
    export MYSQL_INNODB_LOG_FILE_SIZE=${MYSQL_INNODB_LOG_FILE_SIZE:-8M}
    export MYSQL_INNODB_LOG_BUFFER_SIZE=${MYSQL_INNODB_LOG_BUFFER_SIZE:-8M}
  else
    export MYSQL_KEY_BUFFER_SIZE=${MYSQL_KEY_BUFFER_SIZE:-$((MEMORY_LIMIT_IN_BYTES/1024/1024/10))M}
    export MYSQL_READ_BUFFER_SIZE=${MYSQL_READ_BUFFER_SIZE:-$((MEMORY_LIMIT_IN_BYTES/1024/1024/20))M}
    export MYSQL_INNODB_BUFFER_POOL_SIZE=${MYSQL_INNODB_BUFFER_POOL_SIZE:-$((MEMORY_LIMIT_IN_BYTES/1024/1024/2))M}
    # We are multiplying by 15 first and dividing by 100 later so we get as much
    # precision as possible with whole numbers. Result is 15% of memory.
    export MYSQL_INNODB_LOG_FILE_SIZE=${MYSQL_INNODB_LOG_FILE_SIZE:-$((MEMORY_LIMIT_IN_BYTES*15/1024/1024/100))M}
    export MYSQL_INNODB_LOG_BUFFER_SIZE=${MYSQL_INNODB_LOG_BUFFER_SIZE:-$((MEMORY_LIMIT_IN_BYTES*15/1024/1024/100))M}
  fi

This technique is not something new, as we have been doing all the time. e.g  creating customised AMI/ SOE. I think I just need to change my mindset that some traditional skills can still be useful in the container world.

BTW, you can find out the container’s limits from cgroup inside the container . For example /sys/fs/cgroup/memory/memory.limit_in_bytes.

Reference:

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s