Valkey

Published: Apr 16, 2024 by Isaac Johnson

We spoke last week about Redis (the company) abandoning Open-Source licensing for it’s product, Redis (the software). I first heard about Valkey, the larger of the new forks, from The Stack which pointed to that initial fork that was at https://github.com/placeholderkv/placeholderkv (now redirects to Valkey).

On Valkey

The article credits AWS’s Madelyn Olson, a primary Redis software contributor and AliCloud’s Zhou Zhou as the co-creators of the fork. After talking to the displeasure of the license change, Olson commented on Twitter:

“We had a really exciting community roadmap before Redis changed the license. Clustering improvements, performance improvements, triggers, and so much more. We’ll keep driving this forward”

I don’t use “twitter”, but on Mastodon, we can see growing support. @peterzaitsev said “I was excited to see it just took days. It was like, boom: ‘Redis, you choose to [mess with] the community, then Linux Foundation stands behind community.’ I think that was wonderful.” in reference to The Register reporting support from the Linux Foundation.

I also saw Kyle Davis just presented on Valkey at TexasLinuxFest. I would expect more like these in the future.

Since it’s open-source and fresh, let’s dig in and see how well it works.

Installation

Let’s start simple. Let us pull the code and attempt a local compile.

I’ll clone the latest

builder@LuiGi:~/Workspaces$ git clone https://github.com/valkey-io/valkey.git
Cloning into 'valkey'...
remote: Enumerating objects: 92809, done.
remote: Counting objects: 100% (787/787), done.
remote: Compressing objects: 100% (409/409), done.
remote: Total 92809 (delta 498), reused 597 (delta 375), pack-reused 92022
Receiving objects: 100% (92809/92809), 134.68 MiB | 9.06 MiB/s, done.
Resolving deltas: 100% (67779/67779), done.
builder@LuiGi:~/Workspaces$ cd valkey/

Then just run make

builder@LuiGi:~/Workspaces/valkey$ make
cd src && make all
make[1]: Entering directory '/home/builder/Workspaces/valkey/src'
/bin/sh: 1: pkg-config: not found
/bin/sh: 1: pkg-config: not found
/bin/sh: 1: pkg-config: not found
    CC Makefile.dep
/bin/sh: 1: pkg-config: not found
/bin/sh: 1: pkg-config: not found
/bin/sh: 1: pkg-config: not found
rm -rf valkey-server valkey-sentinel valkey-cli valkey-benchmark valkey-check-rdb valkey-check-aof *.o *.gcda *.gcno *.gcov redis.info lcov-html Makefile.dep *.so
rm -f threads_mngr.d adlist.d quicklist.d ae.d anet.d dict.d kvstore.d server.d sds.d zmalloc.d lzf_c.d lzf_d.d pqsort.d zipmap.d sha1.d ziplist.d release.d networking.d util.d object.d db.d replication.d rdb.d t_string.d t_list.d t_set.d t_zset.d t_hash.d config.d aof.d pubsub.d multi.d debug.d sort.d intset.d syncio.d cluster.d cluster_legacy.d crc16.d endianconv.d slowlog.d eval.d bio.d rio.d rand.d memtest.d syscheck.d crcspeed.d crc64.d bitops.d sentinel.d notify.d setproctitle.d blocked.d hyperloglog.d latency.d sparkline.d valkey-check-rdb.d valkey-check-aof.d geo.d lazyfree.d module.d evict.d expire.d geohash.d geohash_helper.d childinfo.d defrag.d siphash.d rax.d t_stream.d listpack.d localtime.d lolwut.d lolwut5.d lolwut6.d acl.d tracking.d socket.d tls.d sha256.d timeout.d setcpuaffinity.d monotonic.d mt19937-64.d resp_parser.d call_reply.d script_lua.d script.d functions.d function_lua.d commands.d strl.d connection.d unix.d logreqres.d anet.d adlist.d dict.d valkey-cli.d zmalloc.d release.d ae.d serverassert.d crcspeed.d crc64.d siphash.d crc16.d monotonic.d cli_common.d mt19937-64.d strl.d cli_commands.d ae.d anet.d valkey-benchmark.d adlist.d dict.d zmalloc.d serverassert.d release.d crcspeed.d crc64.d siphash.d crc16.d monotonic.d cli_common.d mt19937-64.d strl.d
(cd ../deps && make distclean)
make[2]: Entering directory '/home/builder/Workspaces/valkey/deps'
(cd hiredis && make clean) > /dev/null || true
(cd linenoise && make clean) > /dev/null || true
(cd lua && make clean) > /dev/null || true
(cd jemalloc && [ -f Makefile ] && make distclean) > /dev/null || true
(cd hdr_histogram && make clean) > /dev/null || true
(cd fpconv && make clean) > /dev/null || true
(rm -f .make-*)
make[2]: Leaving directory '/home/builder/Workspaces/valkey/deps'
(cd modules && make clean)
make[2]: Entering directory '/home/builder/Workspaces/valkey/src/modules'
rm -rf *.xo *.so
make[2]: Leaving directory '/home/builder/Workspaces/valkey/src/modules'
(cd ../tests/modules && make clean)

... snip ...

Processing json files...
Linking container command to subcommands...
Checking all commands...
Generating commands.def...
All done, exiting.
    CC commands.o
    CC strl.o
    CC connection.o
    CC unix.o
    CC logreqres.o
    LINK valkey-server
    INSTALL valkey-sentinel
    CC valkey-cli.o
    CC serverassert.o
    CC cli_common.o
    CC cli_commands.o
    LINK valkey-cli
    CC valkey-benchmark.o
    LINK valkey-benchmark
    INSTALL valkey-check-rdb
    INSTALL valkey-check-aof

Hint: It's a good idea to run 'make test' ;)

make[1]: Leaving directory '/home/builder/Workspaces/valkey/src'

Now if we want SSL support, we need to ensure we have libssl-dev installed

$ sudo apt-get install libssl-dev

Then can make with SSL support

builder@LuiGi:~/Workspaces/valkey$ make distclean

builder@LuiGi:~/Workspaces/valkey$ make BUILD_TLS=yes
cd src && make all
make[1]: Entering directory '/home/builder/Workspaces/valkey/src'
/bin/sh: 1: pkg-config: not found
/bin/sh: 1: pkg-config: not found
/bin/sh: 1: pkg-config: not found
    CC Makefile.dep
/bin/sh: 1: pkg-config: not found
/bin/sh: 1: pkg-config: not found
/bin/sh: 1: pkg-config: not found
rm -rf valkey-server valkey-sentinel valkey-cli valkey-benchmark valkey-check-rdb valkey-check-aof *.o *.gcda *.gcno *.gcov redis.info lcov-html Makefile.dep *.so
rm -f threads_mngr.d adlist.d quicklist.d ae.d anet.d dict.d kvstore.d server.d sds.d zmalloc.d lzf_c.d lzf_d.d pqsort.d zipmap.d sha1.d ziplist.d release.d networking.d util.d object.d db.d replication.d rdb.d t_string.d t_list.d t_set.d t_zset.d t_hash.d config.d aof.d pubsub.d multi.d debug.d sort.d intset.d syncio.d cluster.d cluster_legacy.d crc16.d endianconv.d slowlog.d eval.d bio.d rio.d rand.d memtest.d syscheck.d crcspeed.d crc64.d bitops.d sentinel.d notify.d setproctitle.d blocked.d hyperloglog.d latency.d sparkline.d valkey-check-rdb.d valkey-check-aof.d geo.d lazyfree.d module.d evict.d expire.d geohash.d geohash_helper.d childinfo.d defrag.d siphash.d rax.d t_stream.d listpack.d localtime.d lolwut.d lolwut5.d lolwut6.d acl.d tracking.d socket.d tls.d sha256.d timeout.d setcpuaffinity.d monotonic.d mt19937-64.d resp_parser.d call_reply.d script_lua.d script.d functions.d function_lua.d commands.d strl.d connection.d unix.d logreqres.d anet.d adlist.d dict.d valkey-cli.d zmalloc.d release.d ae.d serverassert.d crcspeed.d crc64.d siphash.d crc16.d monotonic.d cli_common.d mt19937-64.d strl.d cli_commands.d ae.d anet.d valkey-benchmark.d adlist.d dict.d zmalloc.d serverassert.d release.d crcspeed.d crc64.d siphash.d crc16.d monotonic.d cli_common.d mt19937-64.d strl.d
(cd ../deps && make distclean)

... snip ...

    LINK valkey-server
    INSTALL valkey-sentinel
    CC valkey-cli.o
    CC serverassert.o
    CC cli_common.o
    CC cli_commands.o
    LINK valkey-cli
    CC valkey-benchmark.o
    LINK valkey-benchmark
    INSTALL valkey-check-rdb
    INSTALL valkey-check-aof

Hint: It's a good idea to run 'make test' ;)

make[1]: Leaving directory '/home/builder/Workspaces/valkey/src'

Let’s run some Unit Tests

builder@LuiGi:~/Workspaces/valkey$ ./utils/gen-test-certs.sh
Certificate request self-signature ok
subject=O = Redis Test, CN = Server-only
Certificate request self-signature ok
subject=O = Redis Test, CN = Client-only
Certificate request self-signature ok
subject=O = Redis Test, CN = Generic-cert
Generating DH parameters, 2048 bit long safe prime
....+.........................................................................................................+.+.....................+...............+...........................................................................+................................................................................................................................................................................................................................+.............+..........................+..................................................................................................................................................................................................................................+.............................................................................................................................................................................................................+...............................................................................+........................................................................+..................................................................................................................................................................................+...................................+.........................................................................................+.............................................+............+...........................................................................................................................................................................................+.................................+....................................................................+...+........................................................................................+......................................................................................................+......+..................................................................+..........+..+.................................................................................................................+.......................................................................................+...................................................................................................................................................................................................................................................................................................................................................+..........+..................................+..................+................................................................................................+.................................................................+....................................+............................................


...........++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*

I’ll add TCL so i can run tests

builder@LuiGi:~/Workspaces/valkey$ sudo apt-get install -y tcl
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
  libtcl8.6 tcl8.6
Suggested packages:
  tcl-tclreadline
The following NEW packages will be installed:
  libtcl8.6 tcl tcl8.6
0 upgraded, 3 newly installed, 0 to remove and 0 not upgraded.
Need to get 1009 kB of archives.
After this operation, 4262 kB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu jammy/main amd64 libtcl8.6 amd64 8.6.12+dfsg-1build1 [990 kB]
Get:2 http://archive.ubuntu.com/ubuntu jammy/main amd64 tcl8.6 amd64 8.6.12+dfsg-1build1 [15.0 kB]
Get:3 http://archive.ubuntu.com/ubuntu jammy/main amd64 tcl amd64 8.6.11+1build2 [4678 B]
Fetched 1009 kB in 5s (184 kB/s)
Selecting previously unselected package libtcl8.6:amd64.
(Reading database ... 81862 files and directories currently installed.)
Preparing to unpack .../libtcl8.6_8.6.12+dfsg-1build1_amd64.deb ...
Unpacking libtcl8.6:amd64 (8.6.12+dfsg-1build1) ...
Selecting previously unselected package tcl8.6.
Preparing to unpack .../tcl8.6_8.6.12+dfsg-1build1_amd64.deb ...
Unpacking tcl8.6 (8.6.12+dfsg-1build1) ...
Selecting previously unselected package tcl.
Preparing to unpack .../tcl_8.6.11+1build2_amd64.deb ...
Unpacking tcl (8.6.11+1build2) ...
Setting up libtcl8.6:amd64 (8.6.12+dfsg-1build1) ...
Setting up tcl8.6 (8.6.12+dfsg-1build1) ...
Setting up tcl (8.6.11+1build2) ...
Processing triggers for man-db (2.10.2-1) ...
Processing triggers for libc-bin (2.35-0ubuntu3.6) ...

builder@LuiGi:~/Workspaces/valkey$ sudo apt-get install -y tcl tcl-tls
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
tcl is already the newest version (8.6.11+1build2).
The following NEW packages will be installed:
  tcl-tls
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 68.2 kB of archives.
After this operation, 171 kB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu jammy/universe amd64 tcl-tls amd64 1.7.22-2ubuntu1 [68.2 kB]
Fetched 68.2 kB in 1s (101 kB/s)
Selecting previously unselected package tcl-tls:amd64.
(Reading database ... 82117 files and directories currently installed.)
Preparing to unpack .../tcl-tls_1.7.22-2ubuntu1_amd64.deb ...
Unpacking tcl-tls:amd64 (1.7.22-2ubuntu1) ...
Setting up tcl-tls:amd64 (1.7.22-2ubuntu1) ...

I ran tests.. way too many to show inline

$ ./runtest --tls

/content/images/2024/04/valkey-01.png

I can now run the server

builder@LuiGi:~/Workspaces/valkey/src$ ./valkey-server
3806:C 04 Apr 2024 18:34:35.749 * oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
3806:C 04 Apr 2024 18:34:35.749 * valkey version=255.255.255, bits=64, commit=bb1a3fff, modified=0, pid=3806, just started
3806:C 04 Apr 2024 18:34:35.749 # Warning: no config file specified, using the default config. In order to specify a config file use ./valkey-server /path/to/redis.conf
3806:M 04 Apr 2024 18:34:35.750 * Increased maximum number of open files to 10032 (it was originally set to 1024).
3806:M 04 Apr 2024 18:34:35.750 * monotonic clock: POSIX clock_gettime
                     ___   ___
                    (   ) (   )
 ___  ___    .---.   | |   | |   ___     .--.    ___  ___
(   )(   )  / .-, \  | |   | |  (   )   /    \  (   )(   )   Valkey 255.255.255 (bb1a3fff/0) 64 bit
 | |  | |  (__) ; |  | |   | |  ' /    |  .-. ;  | |  | |
 | |  | |    .'`  |  | |   | |,' /     |  | | |  | |  | |    Running in standalone mode
 | |  | |   / .'| |  | |   | .  '.     |  |/  |  | '  | |    Port: 6379
 | |  | |  | /  | |  | |   | | `. \    |  ' _.'  '  `-' |    PID: 3806
 ' '  ; '  ; |  ; |  | |   | |   \ \   |  .'.-.   `.__. |
  \ `' /   ' `-'  |  | |   | |    \ .  '  `-' /   ___ | |
   \__/    `.__.'_. (___) (___ )  (___) `.__.'   (   )' |    https://valkey.io
                                                  ; `-' '
                                                   .__.'



3806:M 04 Apr 2024 18:34:35.750 * Server initialized
3806:M 04 Apr 2024 18:34:35.750 * Ready to accept connections tcp

/content/images/2024/04/valkey-02.png

I can now test with redis-cli

/content/images/2024/04/valkey-03.png

Container

I’ll be using the current https://github.com/valkey-io/valkey-container.git repo for these next steps.

It contains the Valkey container template that will be using Bashbrew.

Dependencies

First, I’ll need bashbrew.

At first, I though i might get that thru homebrew. homebrew setup in Linux

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"


builder@LuiGi:~/Workspaces/valkey-container$ brew install bashbrew
Command 'brew' not found, did you mean:
  command 'brec' from deb bplay (0.991-10build1)
  command 'qbrew' from deb qbrew (0.4.1-8build1)
Try: sudo apt install <deb name>

Okay, i guess i have to download from Jenkins: https://doi-janky.infosiftr.net/job/bashbrew/job/master/lastSuccessfulBuild/artifact/

I copied it from my Downloads to my WSL instance

builder@LuiGi:~/Workspaces/valkey-container$ sudo cp /mnt/c/Users/isaac/Downloads/bashbrew-amd64 /usr/local/bin/bashbrew
[sudo] password for builder:
builder@LuiGi:~/Workspaces/valkey-container$ sudo chmod 755 /usr/local/bin/bashbrew
builder@LuiGi:~/Workspaces/valkey-container$ bashbrew -h
NAME:
   bashbrew - canonical build tool for the official images

USAGE:
   bashbrew [global options] command [command options] [arguments...]

VERSION:
   v0.1.13

COMMANDS:
   list, ls    list repo:tag combinations for a given repo
   build       build (and tag) repo:tag combinations for a given repo
   tag         tag repo:tag into a namespace (especially for pushing)
   push        push namespace/repo:tag (see also "tag")
   put-shared  update shared tags in the registry (and multi-architecture tags)
   help, h     Shows a list of commands or help for one command

Turning Templates to Dockerfiles

I used apply-templates to create some unstable templates

builder@LuiGi:~/Workspaces/valkey-container$ ./apply-templates.sh
processing unstable/debian ...
processing unstable/alpine ...
builder@LuiGi:~/Workspaces/valkey-container$ ls
Dockerfile.template  LICENSE  README.md  apply-templates.sh  docker-entrypoint.sh  generate-stackbrew-library.sh  unstable  update.sh  versions.json  versions.sh
builder@LuiGi:~/Workspaces/valkey-container$ cat unstable/
alpine/ debian/
builder@LuiGi:~/Workspaces/valkey-container$ cat unstable/alpine/
Dockerfile            docker-entrypoint.sh
builder@LuiGi:~/Workspaces/valkey-container$ cat unstable/alpine/

If there was any doubt, we can cat the end of the file

builder@LuiGi:~/Workspaces/valkey-container/unstable/alpine$ cat Dockerfile | tail -n 5
COPY docker-entrypoint.sh /usr/local/bin/
ENTRYPOINT ["docker-entrypoint.sh"]

EXPOSE 6379
CMD ["valkey-server"]

However, initially, a Docker build died:

4.140 '/usr/local/bin/gosu' saved
4.140 + echo 'bbc4136d03ab138b1ad66fa4fc051bafc6cc7ffae632b069a53657279a450de3 */usr/local/bin/gosu'
4.141 + sha256sum -c -
4.151 /usr/local/bin/gosu: OK
4.151 + mktemp -d
4.152 + export 'GNUPGHOME=/tmp/tmp.fOmBkB'
4.152 + gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4
4.153 gpg: keybox '/tmp/tmp.fOmBkB/pubring.kbx' created
14.19 gpg: keyserver receive failed: Server indicated a failure
------
Dockerfile:25
--------------------
  24 |     ENV GOSU_VERSION 1.17
  25 | >>> RUN set -eux; \
  26 | >>>      apk add --no-cache --virtual .gosu-fetch gnupg; \
  27 | >>>      arch="$(apk --print-arch)"; \
  28 | >>>      case "$arch" in \
  29 | >>>              'x86_64') url='https://github.com/tianon/gosu/releases/download/1.17/gosu-amd64'; sha256='bbc4136d03ab138b1ad66fa4fc051bafc6cc7ffae632b069a53657279a450de3' ;; \
  30 | >>>              'aarch64') url='https://github.com/tianon/gosu/releases/download/1.17/gosu-arm64'; sha256='c3805a85d17f4454c23d7059bcb97e1ec1af272b90126e79ed002342de08389b' ;; \
  31 | >>>              'armhf') url='https://github.com/tianon/gosu/releases/download/1.17/gosu-armhf'; sha256='e5866286277ff2a2159fb9196fea13e0a59d3f1091ea46ddb985160b94b6841b' ;; \
  32 | >>>              'x86') url='https://github.com/tianon/gosu/releases/download/1.17/gosu-i386'; sha256='087dbb8fe479537e64f9c86fa49ff3b41dee1cbd28739a19aaef83dc8186b1ca' ;; \
  33 | >>>              'ppc64le') url='https://github.com/tianon/gosu/releases/download/1.17/gosu-ppc64el'; sha256='1891acdcfa70046818ab6ed3c52b9d42fa10fbb7b340eb429c8c7849691dbd76' ;; \
  34 | >>>              'riscv64') url='https://github.com/tianon/gosu/releases/download/1.17/gosu-riscv64'; sha256='38a6444b57adce135c42d5a3689f616fc7803ddc7a07ff6f946f2ebc67a26ba6' ;; \
  35 | >>>              's390x') url='https://github.com/tianon/gosu/releases/download/1.17/gosu-s390x'; sha256='69873bab588192f760547ca1f75b27cfcf106e9f7403fee6fd0600bc914979d0' ;; \
  36 | >>>              'armv7') url='https://github.com/tianon/gosu/releases/download/1.17/gosu-armhf'; sha256='e5866286277ff2a2159fb9196fea13e0a59d3f1091ea46ddb985160b94b6841b' ;; \
  37 | >>>              *) echo >&2 "error: unsupported gosu architecture: '$arch'"; exit 1 ;; \
  38 | >>>      esac; \
  39 | >>>      wget -O /usr/local/bin/gosu.asc "$url.asc"; \
  40 | >>>      wget -O /usr/local/bin/gosu "$url"; \
  41 | >>>      echo "$sha256 */usr/local/bin/gosu" | sha256sum -c -; \
  42 | >>>      export GNUPGHOME="$(mktemp -d)"; \
  43 | >>>      gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \
  44 | >>>      gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \
  45 | >>>      gpgconf --kill all; \
  46 | >>>      rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \
  47 | >>>      apk del --no-network .gosu-fetch; \
  48 | >>>      chmod +x /usr/local/bin/gosu; \
  49 | >>>      gosu --version; \
  50 | >>>      gosu nobody true
  51 |
--------------------
ERROR: failed to solve: process "/bin/sh -c set -eux; \tapk add --no-cache --virtual .gosu-fetch gnupg; \tarch=\"$(apk --print-arch)\"; \tcase \"$arch\" in \t\t'x86_64') url='https://github.com/tianon/gosu/releases/download/1.17/gosu-amd64'; sha256='bbc4136d03ab138b1ad66fa4fc051bafc6cc7ffae632b069a53657279a450de3' ;; \t\t'aarch64') url='https://github.com/tianon/gosu/releases/download/1.17/gosu-arm64'; sha256='c3805a85d17f4454c23d7059bcb97e1ec1af272b90126e79ed002342de08389b' ;; \t\t'armhf') url='https://github.com/tianon/gosu/releases/download/1.17/gosu-armhf'; sha256='e5866286277ff2a2159fb9196fea13e0a59d3f1091ea46ddb985160b94b6841b' ;; \t\t'x86') url='https://github.com/tianon/gosu/releases/download/1.17/gosu-i386'; sha256='087dbb8fe479537e64f9c86fa49ff3b41dee1cbd28739a19aaef83dc8186b1ca' ;; \t\t'ppc64le') url='https://github.com/tianon/gosu/releases/download/1.17/gosu-ppc64el'; sha256='1891acdcfa70046818ab6ed3c52b9d42fa10fbb7b340eb429c8c7849691dbd76' ;; \t\t'riscv64') url='https://github.com/tianon/gosu/releases/download/1.17/gosu-riscv64'; sha256='38a6444b57adce135c42d5a3689f616fc7803ddc7a07ff6f946f2ebc67a26ba6' ;; \t\t's390x') url='https://github.com/tianon/gosu/releases/download/1.17/gosu-s390x'; sha256='69873bab588192f760547ca1f75b27cfcf106e9f7403fee6fd0600bc914979d0' ;; \t\t'armv7') url='https://github.com/tianon/gosu/releases/download/1.17/gosu-armhf'; sha256='e5866286277ff2a2159fb9196fea13e0a59d3f1091ea46ddb985160b94b6841b' ;; \t\t*) echo >&2 \"error: unsupported gosu architecture: '$arch'\"; exit 1 ;; \tesac; \twget -O /usr/local/bin/gosu.asc \"$url.asc\"; \twget -O /usr/local/bin/gosu \"$url\"; \techo \"$sha256 */usr/local/bin/gosu\" | sha256sum -c -; \texport GNUPGHOME=\"$(mktemp -d)\"; \tgpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \tgpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \tgpgconf --kill all; \trm -rf \"$GNUPGHOME\" /usr/local/bin/gosu.asc; \tapk del --no-network .gosu-fetch; \tchmod +x /usr/local/bin/gosu; \tgosu --version; \tgosu nobody true" did not complete successfully: exit code: 2

I got this error on Debian as well.

The fact is that I’m on a VPN and through a guest wifi presently. I’ll circle back and try at home off VPN next…

Working from my home wifi solved those issues:

$ docker build -t myvalkey-debian-test .
[+] Building 114.6s (14/14) FINISHED                                                                                                                                                       docker:default
 => [internal] load build definition from Dockerfile                                                                                                                                                 0.0s
 => => transferring dockerfile: 7.59kB                                                                                                                                                               0.0s
 => [internal] load metadata for docker.io/library/debian:bookworm-slim                                                                                                                              0.8s
 => [auth] library/debian:pull token for registry-1.docker.io                                                                                                                                        0.0s
 => [internal] load .dockerignore                                                                                                                                                                    0.0s
 => => transferring context: 2B                                                                                                                                                                      0.0s
 => [1/8] FROM docker.io/library/debian:bookworm-slim@sha256:ccb33c3ac5b02588fc1d9e4fc09b952e433d0c54d8618d0ee1afadf1f3cf2455                                                                        0.0s
 => [internal] load build context                                                                                                                                                                    0.0s
 => => transferring context: 42B                                                                                                                                                                     0.0s
 => CACHED [2/8] RUN set -eux;  groupadd -r -g 999 valkey;  useradd -r -g valkey -u 999 valkey                                                                                                       0.0s
 => CACHED [3/8] RUN set -eux;  apt-get update;  apt-get install -y --no-install-recommends   tzdata  ;  rm -rf /var/lib/apt/lists/*                                                                 0.0s
 => [4/8] RUN set -eux;  savedAptMark="$(apt-mark showmanual)";  apt-get update;  apt-get install -y --no-install-recommends ca-certificates gnupg wget;  rm -rf /var/lib/apt/lists/*;  arch="$(dp  26.5s
 => [5/8] RUN set -eux;   savedAptMark="$(apt-mark showmanual)";  apt-get update;  apt-get install -y --no-install-recommends   ca-certificates   wget     dpkg-dev   gcc   libc6-dev   libssl-dev  85.8s
 => [6/8] RUN mkdir /data && chown valkey:valkey /data                                                                                                                                               0.6s
 => [7/8] WORKDIR /data                                                                                                                                                                              0.1s
 => [8/8] COPY docker-entrypoint.sh /usr/local/bin/                                                                                                                                                  0.1s
 => exporting to image                                                                                                                                                                               0.4s
 => => exporting layers                                                                                                                                                                              0.4s
 => => writing image sha256:4254910ab99b4444e6f554aa30627d7208aa0ae58f7c1c27122b3573a6513df0                                                                                                         0.0s
 => => naming to docker.io/library/myvalkey-debian-test                                                                                                                                              0.0s

What's Next?
  View a summary of image vulnerabilities and recommendations → docker scout quickview

So I can see the images

$ docker images
REPOSITORY             TAG       IMAGE ID       CREATED              SIZE
myvalkey-debian-test   latest    4254910ab99b   About a minute ago   138MB

I can then test the image

/content/images/2024/04/valkey-04.png

Kubernetes

Let’s try using this in Kubernetes. To make it easy, I’ll push to Dockerhub.

builder@LuiGi:~/Workspaces/valkey-container/unstable/debian$ docker tag myvalkey-debian-test:latest idjohnson/myvalkey-server:latest
builder@LuiGi:~/Workspaces/valkey-container/unstable/debian$ docker push idjohnson/myvalkey-server:latest
The push refers to repository [docker.io/idjohnson/myvalkey-server]
de35904dc094: Pushed
5f70bf18a086: Pushed
e121f09e2c28: Pushed
0a690c4d99d1: Pushed
a7c6da9ddd24: Pushed
d8b470c15c5a: Pushed
6d157fc1f8ab: Pushed
a483da8ab3e9: Mounted from library/debian
latest: digest: sha256:af21cb4b35290034c45f638f09b148640f580575060f34ae5e7392216b68b09e size: 1987

Next, I’ll get the Bitnami helm charts

builder@LuiGi:~/Workspaces/valkey-container/unstable/debian$ helm repo add bitnami https://charts.bitnami.com/bitnami
WARNING: Kubernetes configuration file is group-readable. This is insecure. Location: /home/builder/.kube/config
WARNING: Kubernetes configuration file is world-readable. This is insecure. Location: /home/builder/.kube/config
"bitnami" has been added to your repositories

builder@LuiGi:~/Workspaces/valkey-container/unstable/debian$ helm repo update
WARNING: Kubernetes configuration file is group-readable. This is insecure. Location: /home/builder/.kube/config
WARNING: Kubernetes configuration file is world-readable. This is insecure. Location: /home/builder/.kube/config
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "bitnami" chart repository
Update Complete. ⎈Happy Helming!⎈

Now I’ll add it to my cluster with helm

$ kubectl create ns valkeytest

$ helm install my-redis -n valkeytest --set image.repository=idjohnson/myvalkey-server --set image.tag=latest bitnami/redis
WARNING: Kubernetes configuration file is group-readable. This is insecure. Location: /home/builder/.kube/config
WARNING: Kubernetes configuration file is world-readable. This is insecure. Location: /home/builder/.kube/config
NAME: my-redis
LAST DEPLOYED: Thu Apr  4 20:35:00 2024
NAMESPACE: valkeytest
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: redis
CHART VERSION: 19.0.2
APP VERSION: 7.2.4

** Please be patient while the chart is being deployed **

Redis&reg; can be accessed on the following DNS names from within your cluster:

    my-redis-master.valkeytest.svc.cluster.local for read/write operations (port 6379)
    my-redis-replicas.valkeytest.svc.cluster.local for read-only operations (port 6379)



To get your password run:

    export REDIS_PASSWORD=$(kubectl get secret --namespace valkeytest my-redis -o jsonpath="{.data.redis-password}" | base64 -d)

To connect to your Redis&reg; server:

1. Run a Redis&reg; pod that you can use as a client:

   kubectl run --namespace valkeytest redis-client --restart='Never'  --env REDIS_PASSWORD=$REDIS_PASSWORD  --image docker.io/idjohnson/myvalkey-server:latest --command -- sleep infinity

   Use the following command to attach to the pod:

   kubectl exec --tty -i redis-client \
   --namespace valkeytest -- bash

2. Connect using the Redis&reg; CLI:
   REDISCLI_AUTH="$REDIS_PASSWORD" redis-cli -h my-redis-master
   REDISCLI_AUTH="$REDIS_PASSWORD" redis-cli -h my-redis-replicas

To connect to your database from outside the cluster execute the following commands:

    kubectl port-forward --namespace valkeytest svc/my-redis-master 6379:6379 &
    REDISCLI_AUTH="$REDIS_PASSWORD" redis-cli -h 127.0.0.1 -p 6379

WARNING: There are "resources" sections in the chart not set. Using "resourcesPreset" is not recommended for production. For production installations, please set the following values according to your workload needs:
  - master.resources
  - replica.resources
+info https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/

I then edited the statefulset to remove the cmd, args and redinessprobes:

$ kubectl get sts -n valkeytest my-redis-master -o yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  annotations:
    meta.helm.sh/release-name: my-redis
    meta.helm.sh/release-namespace: valkeytest
  creationTimestamp: "2024-04-05T01:35:00Z"
  generation: 3
  labels:
    app.kubernetes.io/component: master
    app.kubernetes.io/instance: my-redis
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: redis
    app.kubernetes.io/version: 7.2.4
    helm.sh/chart: redis-19.0.2
  name: my-redis-master
  namespace: valkeytest
  resourceVersion: "5033502"
  uid: bb30313c-9587-444f-8901-1e1db17a09b4
spec:
  podManagementPolicy: OrderedReady
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app.kubernetes.io/component: master
      app.kubernetes.io/instance: my-redis
      app.kubernetes.io/name: redis
  serviceName: my-redis-headless
  template:
    metadata:
      annotations:
        checksum/configmap: 86bcc953bb473748a3d3dc60b7c11f34e60c93519234d4c37f42e22ada559d47
        checksum/health: aff24913d801436ea469d8d374b2ddb3ec4c43ee7ab24663d5f8ff1a1b6991a9
        checksum/scripts: cdd24a5a5914d2c7dc654a082112588ef3e519477676882e617b92b536554aa6
        checksum/secret: e226aa14c1d5c7c42bc7e76f1e761a7fd5a2a5f02c476cc44fb7cc32b81c3161
      creationTimestamp: null
      labels:
        app.kubernetes.io/component: master
        app.kubernetes.io/instance: my-redis
        app.kubernetes.io/managed-by: Helm
        app.kubernetes.io/name: redis
        app.kubernetes.io/version: 7.2.4
        helm.sh/chart: redis-19.0.2
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - podAffinityTerm:
              labelSelector:
                matchLabels:
                  app.kubernetes.io/component: master
                  app.kubernetes.io/instance: my-redis
                  app.kubernetes.io/name: redis
              topologyKey: kubernetes.io/hostname
            weight: 1
      automountServiceAccountToken: false
      containers:
      - env:
        - name: BITNAMI_DEBUG
          value: "false"
        - name: REDIS_REPLICATION_MODE
          value: master
        - name: ALLOW_EMPTY_PASSWORD
          value: "no"
        - name: REDIS_PASSWORD
          valueFrom:
            secretKeyRef:
              key: redis-password
              name: my-redis
        - name: REDIS_TLS_ENABLED
          value: "no"
        - name: REDIS_PORT
          value: "6379"
        image: docker.io/idjohnson/myvalkey-server:latest
        imagePullPolicy: IfNotPresent
        name: redis
        ports:
        - containerPort: 6379
          name: redis
          protocol: TCP
        resources:
          limits:
            cpu: 150m
            ephemeral-storage: 1Gi
            memory: 192Mi
          requests:
            cpu: 100m
            ephemeral-storage: 50Mi
            memory: 128Mi
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop:
            - ALL
          readOnlyRootFilesystem: true
          runAsGroup: 1001
          runAsNonRoot: true
          runAsUser: 1001
          seLinuxOptions: {}
          seccompProfile:
            type: RuntimeDefault
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
        - mountPath: /opt/bitnami/scripts/start-scripts
          name: start-scripts
        - mountPath: /health
          name: health
        - mountPath: /data
          name: redis-data
        - mountPath: /opt/bitnami/redis/mounted-etc
          name: config
        - mountPath: /opt/bitnami/redis/etc/
          name: empty-dir
          subPath: app-conf-dir
        - mountPath: /tmp
          name: empty-dir
          subPath: tmp-dir
      dnsPolicy: ClusterFirst
      enableServiceLinks: true
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext:
        fsGroup: 1001
        fsGroupChangePolicy: Always
      serviceAccount: my-redis-master
      serviceAccountName: my-redis-master
      terminationGracePeriodSeconds: 30
      volumes:
      - configMap:
          defaultMode: 493
          name: my-redis-scripts
        name: start-scripts
      - configMap:
          defaultMode: 493
          name: my-redis-health
        name: health
      - configMap:
          defaultMode: 420
          name: my-redis-configuration
        name: config
      - emptyDir: {}
        name: empty-dir
  updateStrategy:
    type: RollingUpdate
  volumeClaimTemplates:
  - apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      creationTimestamp: null
      labels:
        app.kubernetes.io/component: master
        app.kubernetes.io/instance: my-redis
        app.kubernetes.io/name: redis
      name: redis-data
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 8Gi
      volumeMode: Filesystem
    status:
      phase: Pending
status:
  availableReplicas: 1
  collisionCount: 0
  currentReplicas: 1
  currentRevision: my-redis-master-78f96d6f9
  observedGeneration: 3
  readyReplicas: 1
  replicas: 1
  updateRevision: my-redis-master-78f96d6f9
  updatedReplicas: 1

We can now test

builder@LuiGi:~$ kubectl port-forward --namespace valkeytest svc/my-redis-master 6379:6379 &
[1] 60907

builder@LuiGi:~$ Forwarding from 127.0.0.1:6379 -> 6379
Forwarding from [::1]:6379 -> 6379

builder@LuiGi:~$ REDISCLI_AUTH="$REDIS_PASSWORD" redis-cli -h 127.0.0.1 -p 6379
Handling connection for 6379
Warning: AUTH failed
127.0.0.1:6379> get test
(nil)
127.0.0.1:6379> set testkey val1
OK
127.0.0.1:6379> get testkey
"val1"
127.0.0.1:6379>

Repackaging

Let’s see if we can just regexp the chart to make the regular Bitnami Redis charts into Valkey ones

I’ll pull the latest Redis helm chart

builder@DESKTOP-QADGF36:~/Workspaces/valkey$ helm pull bitnami/redis
builder@DESKTOP-QADGF36:~/Workspaces/valkey$ ls
redis-19.0.1.tgz
builder@DESKTOP-QADGF36:~/Workspaces/valkey$ tar -xzvf redis-19.0.1.tgz
redis/Chart.yaml
redis/Chart.lock
redis/values.yaml
redis/values.schema.json
redis/templates/NOTES.txt
redis/templates/_helpers.tpl
redis/templates/configmap.yaml
redis/templates/extra-list.yaml
redis/templates/headless-svc.yaml
redis/templates/health-configmap.yaml
redis/templates/master/application.yaml
redis/templates/master/psp.yaml
redis/templates/master/pvc.yaml
redis/templates/master/service.yaml
redis/templates/master/serviceaccount.yaml
redis/templates/metrics-svc.yaml
redis/templates/networkpolicy.yaml
redis/templates/pdb.yaml
redis/templates/podmonitor.yaml
redis/templates/prometheusrule.yaml
redis/templates/replicas/application.yaml
redis/templates/replicas/hpa.yaml
redis/templates/replicas/service.yaml
redis/templates/replicas/serviceaccount.yaml
redis/templates/role.yaml
redis/templates/rolebinding.yaml
redis/templates/scripts-configmap.yaml
redis/templates/secret-svcbind.yaml
redis/templates/secret.yaml
redis/templates/sentinel/hpa.yaml
redis/templates/sentinel/node-services.yaml
redis/templates/sentinel/ports-configmap.yaml
redis/templates/sentinel/service.yaml
redis/templates/sentinel/statefulset.yaml
redis/templates/serviceaccount.yaml
redis/templates/servicemonitor.yaml
redis/templates/tls-secret.yaml
redis/.helmignore
redis/README.md
redis/charts/common/Chart.yaml
redis/charts/common/values.yaml
redis/charts/common/templates/_affinities.tpl
redis/charts/common/templates/_capabilities.tpl
redis/charts/common/templates/_compatibility.tpl
redis/charts/common/templates/_errors.tpl
redis/charts/common/templates/_images.tpl
redis/charts/common/templates/_ingress.tpl
redis/charts/common/templates/_labels.tpl
redis/charts/common/templates/_names.tpl
redis/charts/common/templates/_resources.tpl
redis/charts/common/templates/_secrets.tpl
redis/charts/common/templates/_storage.tpl
redis/charts/common/templates/_tplvalues.tpl
redis/charts/common/templates/_utils.tpl
redis/charts/common/templates/_warnings.tpl
redis/charts/common/templates/validations/_cassandra.tpl
redis/charts/common/templates/validations/_mariadb.tpl
redis/charts/common/templates/validations/_mongodb.tpl
redis/charts/common/templates/validations/_mysql.tpl
redis/charts/common/templates/validations/_postgresql.tpl
redis/charts/common/templates/validations/_redis.tpl
redis/charts/common/templates/validations/_validations.tpl
redis/charts/common/.helmignore
redis/charts/common/README.md

Do a quick find sed

builder@DESKTOP-QADGF36:~/Workspaces/valkey$ cd redis/
builder@DESKTOP-QADGF36:~/Workspaces/valkey/redis$ ls
Chart.lock  Chart.yaml  README.md  charts  templates  values.schema.json  values.yaml
builder@DESKTOP-QADGF36:~/Workspaces/valkey/redis$ find . -type f -exec sed -i 's/redis/valkey/g' {} \;

I can see that won’t work because there are dependant containers like exporter and sentinel that don’t exist yet in Docker hub

builder@DESKTOP-QADGF36:~/Workspaces/valkey/redis$ cat Chart.yaml
annotations:
  category: Database
  images: |
    - name: kubectl
      image: docker.io/bitnami/kubectl:1.29.2-debian-12-r3
    - name: os-shell
      image: docker.io/bitnami/os-shell:12-debian-12-r16
    - name: valkey
      image: docker.io/bitnami/valkey:7.2.4-debian-12-r9
    - name: valkey-exporter
      image: docker.io/bitnami/valkey-exporter:1.58.0-debian-12-r4
    - name: valkey-sentinel
      image: docker.io/bitnami/valkey-sentinel:7.2.4-debian-12-r7
  licenses: Apache-2.0
apiVersion: v2
appVersion: 7.2.4
dependencies:
- name: common
  repository: oci://registry-1.docker.io/bitnamicharts
  tags:
  - bitnami-common
  version: 2.x.x
description: Redis(R) is an open source, advanced key-value store. It is often referred
  to as a data structure server since keys can contain strings, hashes, lists, sets
  and sorted sets.
home: https://bitnami.com
icon: https://bitnami.com/assets/stacks/valkey/img/valkey-stack-220x234.png
keywords:
- valkey
- keyvalue
- database
maintainers:
- name: VMware, Inc.
  url: https://github.com/bitnami/charts
name: valkey
sources:
- https://github.com/bitnami/charts/tree/main/bitnami/valkey
version: 19.0.1

We could go down the path of building them all and using our own containers, or just wait until such time we see some official bitnami containers here

/content/images/2024/04/valkey-06.png

Summary

Today we built and ran Valkey, the Open-Source Redis fork, locally. We actually didn’t try building the client as we were testing how well Valkey works with the current Redis-cli. We then pivoted to building and running Valkey in Docker and lastly, we sort of shoe-horned it into Kubernetes using a bastardized Redis helm chart.

It wouldn’t take much to go the next mile to build out all fresh containers and charts. I would rather get those from the OS project or Bitnami.

Valkey Redis OpenSource Containers Kubernetes

Have something to add? Feedback? Try our new forums

Isaac Johnson

Isaac Johnson

Cloud Solutions Architect

Isaac is a CSA and DevOps engineer who focuses on cloud migrations and devops processes. He also is a dad to three wonderful daughters (hence the references to Princess King sprinkled throughout the blog).

Theme built by C.S. Rhymes