PCEtLXtzdWJ0ZW1wbGF0ZSBjb21tb24vaGVhZGVyX2NvbW1vbn0tLT4JPCEtLXtpZiAkX0dFVFsnbW9kJ10gPT0gJ3ZpZXd0aHJlYWQnICYmICFlbXB0eSgkX0dbJ3RpZCddKX0tLT4KCTxsaW5rIHJlbD0iY2Fub25pY2FsIiBocmVmPSJodHRwczovL3d3dy5xaWRhbzEyMy5jb20vYmJzL3RocmVhZC17JF9HWyd0aWQnXX0tMS0xLmh0bWwiIC8+Cgk8IS0te2Vsc2VpZiAkX0dFVFsnbW9kJ10gPT0gJ2ZvcnVtZGlzcGxheScgJiYgIWVtcHR5KCRfR1snZmlkJ10pfS0tPgoJPGxpbmsgcmVsPSJjYW5vbmljYWwiIGhyZWY9Imh0dHBzOi8vd3d3LnFpZGFvMTIzLmNvbS9iYnMvZm9ydW0teyRfR1snZmlkJ119LTEuaHRtbCIgLz4KCTwhLS17ZWxzZWlmICRfR0VUWydtb2QnXSA9PSAnZ3VpZGUnfS0tPgoJPGxpbmsgcmVsPSJjYW5vbmljYWwiIGhyZWY9Imh0dHBzOi8vd3d3LnFpZGFvMTIzLmNvbS9iYnMvZ3VpZGUvIiAvPgoJPCEtLXtlbHNlaWYgJF9HWydiYXNlc2NyaXB0J10gPT0gJ2ZvcnVtJyAmJiAoZW1wdHkoJF9HRVRbJ21vZCddKSB8fCAkX0dFVFsnbW9kJ10gPT0gJ2luZGV4Jyl9LS0+Cgk8bGluayByZWw9ImNhbm9uaWNhbCIgaHJlZj0iaHR0cHM6Ly93d3cucWlkYW8xMjMuY29tL2Jicy8iIC8+Cgk8IS0tey9pZn0tLT4KCXJgbmB0PG1ldGEgbmFtZT0iYXBwbGljYXRpb24tbmFtZSIgY29udGVudD0iJF9HWydzZXR0aW5nJ11bJ2JibmFtZSddIiAvPgoJPG1ldGEgbmFtZT0ibXNhcHBsaWNhdGlvbi10b29sdGlwIiBjb250ZW50PSIkX0dbJ3NldHRpbmcnXVsnYmJuYW1lJ10iIC8+Cgk8IS0te2lmICRfR1snc2V0dGluZyddWydwb3J0YWxzdGF0dXMnXX0tLT48bWV0YSBuYW1lPSJtc2FwcGxpY2F0aW9uLXRhc2siIGNvbnRlbnQ9Im5hbWU9JF9HWydzZXR0aW5nJ11bJ25hdnMnXVsxXVsnbmF2bmFtZSddO2FjdGlvbi11cmk9e2VjaG8gIWVtcHR5KCRfR1snc2V0dGluZyddWydkb21haW4nXVsnYXBwJ11bJ3BvcnRhbCddKSA/ICRfR1snc2NoZW1lJ10uJzovLycuJF9HWydzZXR0aW5nJ11bJ2RvbWFpbiddWydhcHAnXVsncG9ydGFsJ10gOiAkX0dbc2l0ZXVybF0uJ3BvcnRhbC5waHAnfTtpY29uLXVyaT17JF9HW3NpdGV1cmxdfXtJTUdESVJ9L3BvcnRhbC5pY28iIC8+PCEtLXsvaWZ9LS0+Cgk8bWV0YSBuYW1lPSJtc2FwcGxpY2F0aW9uLXRhc2siIGNvbnRlbnQ9Im5hbWU9JF9HWydzZXR0aW5nJ11bJ25hdnMnXVsyXVsnbmF2bmFtZSddO2FjdGlvbi11cmk9e2VjaG8gIWVtcHR5KCRfR1snc2V0dGluZyddWydkb21haW4nXVsnYXBwJ11bJ2ZvcnVtJ10pID8gJF9HWydzY2hlbWUnXS4nOi8vJy4kX0dbJ3NldHRpbmcnXVsnZG9tYWluJ11bJ2FwcCddWydmb3J1bSddIDogJF9HW3NpdGV1cmxdLidmb3J1bS5waHAnfTtpY29uLXVyaT17JF9HW3NpdGV1cmxdfXtJTUdESVJ9L2Jicy5pY28iIC8+Cgk8IS0te2lmICRfR1snc2V0dGluZyddWydncm91cHN0YXR1cyddfS0tPjxtZXRhIG5hbWU9Im1zYXBwbGljYXRpb24tdGFzayIgY29udGVudD0ibmFtZT0kX0dbJ3NldHRpbmcnXVsnbmF2cyddWzNdWyduYXZuYW1lJ107YWN0aW9uLXVyaT17ZWNobyAhZW1wdHkoJF9HWydzZXR0aW5nJ11bJ2RvbWFpbiddWydhcHAnXVsnZ3JvdXAnXSkgPyAkX0dbJ3NjaGVtZSddLic6Ly8nLiRfR1snc2V0dGluZyddWydkb21haW4nXVsnYXBwJ11bJ2dyb3VwJ10gOiAkX0dbc2l0ZXVybF0uJ2dyb3VwLnBocCd9O2ljb24tdXJpPXskX0dbc2l0ZXVybF19e0lNR0RJUn0vZ3JvdXAuaWNvIiAvPjwhLS17L2lmfS0tPgoJPCEtLXtpZiBoZWxwZXJfYWNjZXNzOjpjaGVja19tb2R1bGUoJ2ZlZWQnKX0tLT48bWV0YSBuYW1lPSJtc2FwcGxpY2F0aW9uLXRhc2siIGNvbnRlbnQ9Im5hbWU9JF9HWydzZXR0aW5nJ11bJ25hdnMnXVs0XVsnbmF2bmFtZSddO2FjdGlvbi11cmk9e2VjaG8gIWVtcHR5KCRfR1snc2V0dGluZyddWydkb21haW4nXVsnYXBwJ11bJ2hvbWUnXSkgPyAkX0dbJ3NjaGVtZSddLic6Ly8nLiRfR1snc2V0dGluZyddWydkb21haW4nXVsnYXBwJ11bJ2hvbWUnXSA6ICRfR1tzaXRldXJsXS4naG9tZS5waHAnfTtpY29uLXVyaT17JF9HW3NpdGV1cmxdfXtJTUdESVJ9L2hvbWUuaWNvIiAvPjwhLS17L2lmfS0tPgoJPCEtLXtpZiAkX0dbJ2Jhc2VzY3JpcHQnXSA9PSAnZm9ydW0nICYmICRfR1snc2V0dGluZyddWydhcmNoaXZlciddfS0tPgoJCTxsaW5rIHJlbD0iYXJjaGl2ZXMiIHRpdGxlPSIkX0dbJ3NldHRpbmcnXVsnYmJuYW1lJ10iIGhyZWY9InskX0dbc2l0ZXVybF19YXJjaGl2ZXIvIiAvPgoJPCEtLXsvaWZ9LS0+Cgk8IS0te2lmICFlbXB0eSgkcnNzaGVhZCl9LS0+JHJzc2hlYWQ8IS0tey9pZn0tLT4KCTwhLS17aWYgd2lkdGhhdXRvKCl9LS0+CgkJPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBpZD0iY3NzX3dpZHRoYXV0byIgdHlwZT0idGV4dC9jc3MiIGhyZWY9J3skX0dbJ3NldHRpbmcnXVsnY3NzcGF0aCddfXtTVFlMRUlEfV93aWR0aGF1dG8uY3NzP3tWRVJIQVNIfScgLz4KCQk8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCI+SFRNTE5PREUuY2xhc3NOYW1lICs9ICcgd2lkdGhhdXRvJzwvc2NyaXB0PgoJPCEtLXsvaWZ9LS0+Cgk8IS0te2lmICRfR1snYmFzZXNjcmlwdCddID09ICdmb3J1bScgfHwgJF9HWydiYXNlc2NyaXB0J10gPT0gJ2dyb3VwJ30tLT4KCQk8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCIgc3JjPSJ7JF9HW3NldHRpbmddW2pzcGF0aF19Zm9ydW0uanM/e1ZFUkhBU0h9Ij48L3NjcmlwdD4KCTwhLS17ZWxzZWlmICRfR1snYmFzZXNjcmlwdCddID09ICdob21lJ30tLT4KCQk8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCIgc3JjPSJ7JF9HW3NldHRpbmddW2pzcGF0aF19aG9tZS5qcz97VkVSSEFTSH0iPjwvc2NyaXB0PgoJPCEtLXtlbHNlaWYgJF9HWydiYXNlc2NyaXB0J10gPT0gJ3BvcnRhbCd9LS0+CgkJPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiIHNyYz0ieyRfR1tzZXR0aW5nXVtqc3BhdGhdfXBvcnRhbC5qcz97VkVSSEFTSH0iPjwvc2NyaXB0PgoJPCEtLXsvaWZ9LS0+Cgk8IS0te2lmICRfR1snYmFzZXNjcmlwdCddICE9ICdwb3J0YWwnICYmICRfR0VUWydkaXknXSA9PSAneWVzJyAmJiBjaGVja19kaXlfcGVybSgkdG9waWMpfS0tPgoJCTxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0IiBzcmM9InskX0dbc2V0dGluZ11banNwYXRoXX1wb3J0YWwuanM/e1ZFUkhBU0h9Ij48L3NjcmlwdD4KCTwhLS17L2lmfS0tPgoJPCEtLXtpZiAkX0dFVFsnZGl5J10gPT0gJ3llcycgJiYgY2hlY2tfZGl5X3Blcm0oJHRvcGljKX0tLT4KCQk8bGluayByZWw9InN0eWxlc2hlZXQiIHR5cGU9InRleHQvY3NzIiBpZD0iZGl5X2NvbW1vbiIgaHJlZj0ieyRfR1snc2V0dGluZyddWydjc3NwYXRoJ119e1NUWUxFSUR9X2Nzc19kaXkuY3NzP3tWRVJIQVNIfSIgLz4KCTwhLS17L2lmfS0tPgo8L2hlYWQ+Cgo8Ym9keSBpZD0ibnZfeyRfR1tiYXNlc2NyaXB0XX0iIGNsYXNzPSJwZ197Q1VSTU9EVUxFfXtpZiAkX0dbJ2Jhc2VzY3JpcHQnXSA9PT0gJ3BvcnRhbCcgJiYgQ1VSTU9EVUxFID09PSAnbGlzdCcgJiYgIWVtcHR5KCRjYXQpfSB7JGNhdFsnYm9keWNzcyddfXsvaWZ9IiBvbmtleWRvd249ImlmKGV2ZW50LmtleUNvZGU9PTI3KSByZXR1cm4gZmFsc2U7Ij4KCTxkaXYgaWQ9ImFwcGVuZF9wYXJlbnQiPjwvZGl2PjxkaXYgaWQ9ImFqYXh3YWl0aWQiPjwvZGl2PgoJPCEtLXtpZiAkX0dFVFsnZGl5J10gPT0gJ3llcycgJiYgY2hlY2tfZGl5X3Blcm0oJHRvcGljKX0tLT4KCQk8IS0te3RlbXBsYXRlIGNvbW1vbi9oZWFkZXJfZGl5fS0tPgoJPCEtLXsvaWZ9LS0+Cgk8IS0te2lmIGNoZWNrX2RpeV9wZXJtKCR0b3BpYyl9LS0+CgkJPCEtLXt0ZW1wbGF0ZSBjb21tb24vaGVhZGVyX2RpeW5hdn0tLT4KCTwhLS17L2lmfS0tPgoJPCEtLXtpZiBDVVJNT0RVTEUgPT0gJ3RvcGljJyAmJiAkdG9waWMgJiYgZW1wdHkoJHRvcGljWyd1c2VoZWFkZXInXSkgJiYgY2hlY2tfZGl5X3Blcm0oJHRvcGljKX0tLT4KCQkkZGl5bmF2Cgk8IS0tey9pZn0tLT4KCTwhLS17aWYgZW1wdHkoJHRvcGljKSB8fCAkdG9waWNbJ3VzZWhlYWRlciddfS0tPgoJCTwhLS17aWYgJF9HWydzZXR0aW5nJ11bJ21vYmlsZSddWydhbGxvd21vYmlsZSddICYmICghJF9HWydzZXR0aW5nJ11bJ2NhY2hlaW5kZXhsaWZlJ10gJiYgISRfR1snc2V0dGluZyddWydjYWNoZXRocmVhZG9uJ10gfHwgJF9HWyd1aWQnXSkgJiYgKCRfR0VUWydkaXknXSAhPSAneWVzJyB8fCAhJF9HRVRbJ2luYWpheCddKSAmJiAoJF9HWydtb2JpbGUnXSAhPSAnJyAmJiAkX0dbJ2Nvb2tpZSddWydtb2JpbGUnXSA9PSAnJyAmJiAkX0dFVFsnbW9iaWxlJ10gIT0gJ25vJyl9LS0+CgkJCTxkaXYgY2xhc3M9InhpMSBibSBibV9jIj4KCQkJICAgIHtsYW5nIHlvdXJfbW9iaWxlX2Jyb3dzZXJ9PGEgaHJlZj0ieyRfR1snc2l0ZXVybCddfWZvcnVtLnBocD9tb2JpbGU9eWVzIj57bGFuZyBnb190b19tb2JpbGV9PC9hPiA8c3BhbiBjbGFzcz0ieGcxIj58PC9zcGFuPiA8YSBocmVmPSIkX0dbJ3NldHRpbmcnXVsnbW9iaWxlJ11bJ25vbW9iaWxldXJsJ10iPntsYW5nIHRvX2JlX2NvbnRpbnVlfTwvYT4KCQkJPC9kaXY+CgkJPCEtLXsvaWZ9LS0+CgkJPCEtLXtpZiAhZW1wdHkoJF9HWydzZXR0aW5nJ11bJ3Nob3J0Y3V0J10pICYmICRfR1snbWVtYmVyJ11bY3JlZGl0c10gPj0gJF9HWydzZXR0aW5nJ11bJ3Nob3J0Y3V0J119LS0+CgkJCTxkaXYgaWQ9InNob3J0Y3V0Ij4KCQkJCTxzcGFuPjxhIGhyZWY9ImphdmFzY3JpcHQ6OyIgaWQ9InNob3J0Y3V0Y2xvc2VpZCIgdGl0bGU9IntsYW5nIGNsb3NlfSI+e2xhbmcgY2xvc2V9PC9hPjwvc3Bhbj4KCQkJCXtsYW5nIHNob3J0Y3V0X25vdGljZX0KCQkJCTxhIGhyZWY9ImphdmFzY3JpcHQ6OyIgaWQ9InNob3J0Y3V0dGlwIj57bGFuZyBzaG9ydGN1dF9hZGR9PC9hPgoKCQkJPC9kaXY+CgkJCTxzY3JpcHQgdHlwZT0idGV4dC9qYXZhc2NyaXB0Ij5zZXRUaW1lb3V0KHNldFNob3J0Y3V0LCAyMDAwKTs8L3NjcmlwdD4KCQk8IS0tey9pZn0tLT4KCQk8ZGl2IGlkPSJ0b3B0YiIgY2xhc3M9ImNsIj4KCQkJPCEtLXtob29rL2dsb2JhbF9jcG5hdl90b3B9LS0+CgkJCTxkaXYgY2xhc3M9IndwIj4KCQkJCTxkaXYgY2xhc3M9InoiPgoJCQkJCTwhLS17bG9vcCAkX0dbJ3NldHRpbmcnXVsndG9wbmF2cyddWzBdICRuYXZ9LS0+CgkJCQkJCTwhLS17aWYgaXNfYXJyYXkoJG5hdikgJiYgJG5hdlsnYXZhaWxhYmxlJ10gJiYgKCEkbmF2WydsZXZlbCddIHx8ICgkbmF2WydsZXZlbCddID09IDEgJiYgJF9HWyd1aWQnXSkgfHwgKCRuYXZbJ2xldmVsJ10gPT0gMiAmJiAkX0dbJ2FkbWluaWQnXSA+IDApIHx8ICgkbmF2WydsZXZlbCddID09IDMgJiYgJF9HWydhZG1pbmlkJ10gPT0gMSkpfS0tPiRuYXZbY29kZV08IS0tey9pZn0tLT4KCQkJCQk8IS0tey9sb29wfS0tPgoJCQkJCTwhLS17aG9vay9nbG9iYWxfY3BuYXZfZXh0cmExfS0tPgoJCQkJPC9kaXY+CgkJCQk8ZGl2IGNsYXNzPSJ5Ij4KCQkJCQk8YSBpZD0ic3dpdGNoYmxpbmQiIGhyZWY9ImphdmFzY3JpcHQ6OyIgb25jbGljaz0idG9nZ2xlQmxpbmQodGhpcykiIHRpdGxlPSJ7bGFuZyBzd2l0Y2hfYmxpbmR9IiBjbGFzcz0ic3dpdGNoYmxpbmQiPjwvYT4KCQkJCQk8IS0te2hvb2svZ2xvYmFsX2NwbmF2X2V4dHJhMn0tLT4KCQkJCQk8IS0te2xvb3AgJF9HWydzZXR0aW5nJ11bJ3RvcG5hdnMnXVsxXSAkbmF2fS0tPgoJCQkJCQk8IS0te2lmIGlzX2FycmF5KCRuYXYpICYmICRuYXZbJ2F2YWlsYWJsZSddICYmICghJG5hdlsnbGV2ZWwnXSB8fCAoJG5hdlsnbGV2ZWwnXSA9PSAxICYmICRfR1sndWlkJ10pIHx8ICgkbmF2WydsZXZlbCddID09IDIgJiYgJF9HWydhZG1pbmlkJ10gPiAwKSB8fCAoJG5hdlsnbGV2ZWwnXSA9PSAzICYmICRfR1snYWRtaW5pZCddID09IDEpKX0tLT4kbmF2W2NvZGVdPCEtLXsvaWZ9LS0+CgkJCQkJPCEtLXsvbG9vcH0tLT4KCQkJCQk8IS0te2lmIGVtcHR5KCRfR1snZGlzYWJsZWR3aWR0aGF1dG8nXSkgJiYgJF9HWydzZXR0aW5nJ11bJ3N3aXRjaHdpZHRoYXV0byddfS0tPgoJCQkJCQk8YSBocmVmPSJqYXZhc2NyaXB0OjsiIGlkPSJzd2l0Y2h3aWR0aCIgb25jbGljaz0id2lkdGhhdXRvKHRoaXMpIiB0aXRsZT0ie2lmIHdpZHRoYXV0bygpfXtsYW5nIHN3aXRjaF9uYXJyb3d9e2Vsc2V9e2xhbmcgc3dpdGNoX3dpZGV9ey9pZn0iIGNsYXNzPSJzd2l0Y2h3aWR0aCI+PCEtLXtpZiB3aWR0aGF1dG8oKX0tLT57bGFuZyBzd2l0Y2hfbmFycm93fTwhLS17ZWxzZX0tLT57bGFuZyBzd2l0Y2hfd2lkZX08IS0tey9pZn0tLT48L2E+CgkJCQkJPCEtLXsvaWZ9LS0+CgkJCQkJPCEtLXtpZiAkX0dbJ3VpZCddICYmICFlbXB0eSgkX0dbJ3N0eWxlJ11bJ2V4dHN0eWxlJ10pfS0tPjxhIGlkPSJzc2xjdCIgaHJlZj0iamF2YXNjcmlwdDo7IiBvbm1vdXNlb3Zlcj0iZGVsYXlTaG93KHRoaXMsIGZ1bmN0aW9uKCkge3Nob3dNZW51KHsnY3RybGlkJzonc3NsY3QnLCdwb3MnOiczNCEnfSl9KTsiPntsYW5nIGNoYW5nZXN0eWxlfTwvYT48IS0tey9pZn0tLT4KCQkJCQk8IS0te2lmIGNoZWNrX2RpeV9wZXJtKCR0b3BpYyl9LS0+CgkJCQkJCSRkaXluYXYKCQkJCQk8IS0tey9pZn0tLT4KCQkJCTwvZGl2PgoJCQk8L2Rpdj4KCQk8L2Rpdj4KCgkJPCEtLXtpZiAhSVNfUk9CT1R9LS0+CgkJCTwhLS17aWYgJF9HWyd1aWQnXSAmJiAhJF9HWydzZXR0aW5nJ11bJ2JiY2xvc2VkJ10gJiYgZW1wdHkoJF9HWydtZW1iZXInXVsnZnJlZXplJ10pICYmICRfR1snbWVtYmVyJ11bJ2dyb3VwaWQnXSAhPSA1fS0tPgoJCQk8dWwgaWQ9Im15cHJvbXB0X21lbnUiIGNsYXNzPSJwX3BvcCIgc3R5bGU9ImRpc3BsYXk6IG5vbmU7Ij4KCQkJCTxsaT48YSBocmVmPSJob21lLnBocD9tb2Q9c3BhY2UmZG89cG0iIGlkPSJwbV9udGMiIHN0eWxlPSJiYWNrZ3JvdW5kLXJlcGVhdDogbm8tcmVwZWF0OyBiYWNrZ3JvdW5kLXBvc2l0aW9uOiAwIDUwJTsiPjxlbSBjbGFzcz0icHJvbXB0X25ld3N7aWYgZW1wdHkoJF9HW21lbWJlcl1bbmV3cG1dKX1fMHsvaWZ9Ij48L2VtPntsYW5nIHBtX2NlbnRlcn08L2E+PC9saT4KCQkJCTwhLS17aWYgJF9HWydzZXR0aW5nJ11bJ2ZvbGxvd3N0YXR1cyddfS0tPgoJCQkJCTxsaT48YSBocmVmPSJob21lLnBocD9tb2Q9Zm9sbG93JmRvPWZvbGxvd2VyIj48ZW0gY2xhc3M9InByb21wdF9mb2xsb3dlcntpZiBlbXB0eSgkX0dbbWVtYmVyXVtuZXdwcm9tcHRfbnVtXVtmb2xsb3dlcl0pfV8wey9pZn0iPjwvZW0+PCEtLXtsYW5nIG5vdGljZV9pbnRlcmFjdGl2ZV9mb2xsb3dlcn0tLT57aWYgJF9HW21lbWJlcl1bbmV3cHJvbXB0X251bV1bZm9sbG93ZXJdfSgkX0dbbWVtYmVyXVtuZXdwcm9tcHRfbnVtXVtmb2xsb3dlcl0pey9pZn08L2E+PC9saT4KCQkJCQk8IS0te2lmICRfR1ttZW1iZXJdW25ld3Byb21wdF0gJiYgJF9HW21lbWJlcl1bbmV3cHJvbXB0X251bV1bZm9sbG93XX0tLT4KCQkJCQkJPGxpPjxhIGhyZWY9ImhvbWUucGhwP21vZD1mb2xsb3ciPjxlbSBjbGFzcz0icHJvbXB0X2NvbmNlcm4iPjwvZW0+PCEtLXtsYW5nIG5vdGljZV9pbnRlcmFjdGl2ZV9mb2xsb3d9LS0+KCRfR1ttZW1iZXJdW25ld3Byb21wdF9udW1dW2ZvbGxvd10pPC9hPjwvbGk+CgkJCQkJPCEtLXsvaWZ9LS0+CgkJCQk8IS0tey9pZn0tLT4KCQkJCTwhLS17aWYgJF9HW21lbWJlcl1bbmV3cHJvbXB0XX0tLT4KCQkJCQk8IS0te2xvb3AgJF9HWydtZW1iZXInXVsnY2F0ZWdvcnlfbnVtJ10gJGtleSAkdmFsfS0tPgoJCQkJCQk8bGk+PGEgaHJlZj0iaG9tZS5waHA/bW9kPXNwYWNlJmRvPW5vdGljZSZ2aWV3PSRrZXkiPjxlbSBjbGFzcz0ibm90aWNlXyRrZXkiPjwvZW0+PCEtLXtlY2hvIGxhbmcoJ3RlbXBsYXRlJywgJ25vdGljZV8nLiRrZXkpfS0tPig8c3BhbiBjbGFzcz0icnEiPiR2YWw8L3NwYW4+KTwvYT48L2xpPgoJCQkJCTwhLS17L2xvb3B9LS0+CgkJCQk8IS0tey9pZn0tLT4KCQkJCTwhLS17aWYgZW1wdHkoJF9HWydjb29raWUnXVsnaWdub3JlX25vdGljZSddKX0tLT4KCQkJCQk8bGkgY2xhc3M9Imlnbm9yZV9ub3RpY2VsaSI+PGEgaHJlZj0iamF2YXNjcmlwdDo7IiBvbmNsaWNrPSJzZXRjb29raWUoJ2lnbm9yZV9ub3RpY2UnLCAxKTtoaWRlTWVudSgnbXlwcm9tcHRfbWVudScpIiB0aXRsZT0ie2xhbmcgdGVtcG9yYXJpbHlfdG9fcmVtaW5kfSI+PGVtIGNsYXNzPSJpZ25vcmVfbm90aWNlIj48L2VtPjwvYT48L2xpPgoJCQkJPCEtLXsvaWZ9LS0+CgkJCTwvdWw+CgkJCTwhLS17L2lmfS0tPgoJCQk8IS0te2lmICRfR1sndWlkJ10gJiYgIWVtcHR5KCRfR1snc3R5bGUnXVsnZXh0c3R5bGUnXSl9LS0+CgkJCQk8ZGl2IGlkPSJzc2xjdF9tZW51IiBjbGFzcz0iY2wgcF9wb3AiIHN0eWxlPSJkaXNwbGF5OiBub25lOyI+CgkJCQkJPCEtLXtpZiAhJF9HW3N0eWxlXVtkZWZhdWx0ZXh0c3R5bGVdfS0tPjxzcGFuIGNsYXNzPSJzc2xjdF9idG4iIG9uY2xpY2s9ImV4dHN0eWxlKCcnKSIgdGl0bGU9IntsYW5nIGRlZmF1bHR9Ij48aT48L2k+PC9zcGFuPjwhLS17L2lmfS0tPgoJCQkJCTwhLS17bG9vcCAkX0dbJ3N0eWxlJ11bJ2V4dHN0eWxlJ10gJGV4dHN0eWxlfS0tPgoJCQkJCQk8c3BhbiBjbGFzcz0ic3NsY3RfYnRuIiBvbmNsaWNrPSJleHRzdHlsZSgnJGV4dHN0eWxlWzBdJykiIHRpdGxlPSIkZXh0c3R5bGVbMV0iPjxpIHN0eWxlPSdiYWNrZ3JvdW5kOiRleHRzdHlsZVsyXSc+PC9pPjwvc3Bhbj4KCQkJCQk8IS0tey9sb29wfS0tPgoJCQkJPC9kaXY+CgkJCTwhLS17L2lmfS0tPgoJCQk8IS0te2lmICRfR1sndWlkJ119LS0+CgkJCQk8dWwgaWQ9Im15aXRlbV9tZW51IiBjbGFzcz0icF9wb3AiIHN0eWxlPSJkaXNwbGF5OiBub25lOyI+CgkJCQkJPCEtLXtpZiAkX0dbJ3NldHRpbmcnXVsnZm9ydW1zdGF0dXMnXX0tLT48bGk+PGEgaHJlZj0iaG9tZS5waHA/bW9kPXNwYWNlJmRvPXRocmVhZCZ2aWV3PW1lIj57bGFuZyBteXBvc3R9PC9hPjwvbGk+PCEtLXsvaWZ9LS0+CgkJCQkJPCEtLXtpZiAkX0dbJ3NldHRpbmcnXVsnZmF2b3JpdGVzdGF0dXMnXX0tLT48bGk+PGEgaHJlZj0iaG9tZS5waHA/bW9kPXNwYWNlJmRvPWZhdm9yaXRlJnZpZXc9bWUiPntsYW5nIGZhdm9yaXRlfTwvYT48L2xpPjwhLS17L2lmfS0tPgoJCQkJCTwhLS17aWYgJF9HWydzZXR0aW5nJ11bJ2ZyaWVuZHN0YXR1cyddfS0tPjxsaT48YSBocmVmPSJob21lLnBocD9tb2Q9c3BhY2UmZG89ZnJpZW5kIj57bGFuZyBmcmllbmRzfTwvYT48L2xpPjwhLS17L2lmfS0tPgoJCQkJCTwhLS17aG9vay9nbG9iYWxfbXlpdGVtX2V4dHJhfS0tPgoJCQkJPC91bD4KCQkJPCEtLXsvaWZ9LS0+CgkJCTwhLS17c3VidGVtcGxhdGUgY29tbW9uL2hlYWRlcl9xbWVudX0tLT4KCQk8IS0tey9pZn0tLT4KCgkJPCEtLXthZC9oZWFkZXJiYW5uZXIvd3AgYV9ofS0tPgoJCTxkaXYgaWQ9ImhkIj4KCQkJPGRpdiBjbGFzcz0id3AiPgoJCQkJPGRpdiBjbGFzcz0iaGRjIGNsIj4KCQkJCQk8IS0te2V2YWwgJG1uaWQgPSBnZXRjdXJyZW50bmF2KCk7fS0tPgoJCQkJCTxoMj48IS0te2lmICFpc3NldCgkX0dbJ3NldHRpbmcnXVsnbmF2bG9nb3MnXVskbW5pZF0pfS0tPjxhIGhyZWY9IntpZiAkX0dbJ3NldHRpbmcnXVsnZG9tYWluJ11bJ2FwcCddWydkZWZhdWx0J119eyRfR1snc2NoZW1lJ119Oi8veyRfR1snc2V0dGluZyddWydkb21haW4nXVsnYXBwJ11bJ2RlZmF1bHQnXX0ve2Vsc2V9Li97L2lmfSIgdGl0bGU9IiRfR1snc2V0dGluZyddWydiYm5hbWUnXSI+eyRfR1snc3R5bGUnXVsnYm9hcmRsb2dvJ119PC9hPjwhLS17ZWxzZX0tLT4kX0dbJ3NldHRpbmcnXVsnbmF2bG9nb3MnXVskbW5pZF08IS0tey9pZn0tLT48L2gyPgoJCQkJCTwhLS17dGVtcGxhdGUgY29tbW9uL2hlYWRlcl91c2Vyc3RhdHVzfS0tPgoJCQkJPC9kaXY+CgoJCQkJPGRpdiBpZD0ibnYiPgoJCQkJCTxhIGhyZWY9ImphdmFzY3JpcHQ6OyIgaWQ9InFtZW51IiBvbm1vdXNlb3Zlcj0iZGVsYXlTaG93KHRoaXMsIGZ1bmN0aW9uICgpIHtzaG93TWVudSh7J2N0cmxpZCc6J3FtZW51JywncG9zJzonMzQhJywnY3RybGNsYXNzJzonYScsJ2R1cmF0aW9uJzoyfSk7c2hvd0ZvcnVtbWVudSgkX0dbZmlkXSk7fSkiPntsYW5nIG15X25hdn08L2E+CgkJCQkJPHVsPgoJCQkJCQk8IS0te2xvb3AgJF9HWydzZXR0aW5nJ11bJ25hdnMnXSAkbmF2fS0tPgoJCQkJCQkJPCEtLXtpZiBpc19hcnJheSgkbmF2KSAmJiAkbmF2WydhdmFpbGFibGUnXSAmJiAoISRuYXZbJ2xldmVsJ10gfHwgKCRuYXZbJ2xldmVsJ10gPT0gMSAmJiAkX0dbJ3VpZCddKSB8fCAoJG5hdlsnbGV2ZWwnXSA9PSAyICYmICRfR1snYWRtaW5pZCddID4gMCkgfHwgKCRuYXZbJ2xldmVsJ10gPT0gMyAmJiAkX0dbJ2FkbWluaWQnXSA9PSAxKSl9LS0+PGxpIHtpZiAkbW5pZCA9PSAkbmF2W25hdmlkXSB8fCBzdWJzdHIoJF9TRVJWRVJbJ1JFUVVFU1RfVVJJJ10sIDEpID09IHN0cl9yZXBsYWNlKCcuLycsICcnLCAkbmF2W2ZpbGVuYW1lXSl9Y2xhc3M9ImEiIHsvaWZ9JG5hdltuYXZdPjwvbGk+PCEtLXsvaWZ9LS0+CgkJCQkJCTwhLS17L2xvb3B9LS0+CgkJCQkJPC91bD4KCQkJCQk8IS0te2hvb2svZ2xvYmFsX25hdl9leHRyYX0tLT4KCQkJCTwvZGl2PgoJCQkJPCEtLXtpZiAhZW1wdHkoJF9HWydzZXR0aW5nJ11bJ3BsdWdpbnMnXVsnanNtZW51J10pfS0tPgoJCQkJCTx1bCBjbGFzcz0icF9wb3AgaF9wb3AiIGlkPSJwbHVnaW5fbWVudSIgc3R5bGU9ImRpc3BsYXk6IG5vbmUiPgoJCQkJCTwhLS17bG9vcCAkX0dbJ3NldHRpbmcnXVsncGx1Z2lucyddWydqc21lbnUnXSAkbW9kdWxlfS0tPgoJCQkJCQkgPCEtLXtpZiBpbl9hcnJheSgkbW9kdWxlWydhZG1pbmlkJ10sIGFycmF5KDAsIC0xKSkgfHwgKCRtb2R1bGVbJ2FkbWluaWQnXSAmJiAkX0dbJ2FkbWluaWQnXSA+IDAgJiYgJG1vZHVsZVsnYWRtaW5pZCddID49ICRfR1snYWRtaW5pZCddKX0tLT4KCQkJCQkJIDxsaT4kbW9kdWxlW3VybF08L2xpPgoJCQkJCQkgPCEtLXsvaWZ9LS0+CgkJCQkJPCEtLXsvbG9vcH0tLT4KCQkJCQk8L3VsPgoJCQkJPCEtLXsvaWZ9LS0+CgkJCQkkX0dbc2V0dGluZ11bbWVudW5hdnNdCgkJCQk8ZGl2IGlkPSJtdSIgY2xhc3M9ImNsIj4KCQkJCTwhLS17aWYgJF9HWydzZXR0aW5nJ11bJ3N1Ym5hdnMnXX0tLT4KCQkJCQk8IS0te2xvb3AgJF9HW3NldHRpbmddW3N1Ym5hdnNdICRuYXZpZCAkc3VibmF2fS0tPgoJCQkJCQk8IS0te2lmICRfR1snc2V0dGluZyddWyduYXZzdWJob3ZlciddIHx8ICRtbmlkID09ICRuYXZpZH0tLT4KCQkJCQkJPHVsIGNsYXNzPSJjbCB7aWYgJG1uaWQgPT0gJG5hdmlkfWN1cnJlbnR7L2lmfSIgaWQ9InNuYXZfJG5hdmlkIntpZiAkbW5pZCAhPSAkbmF2aWR9IHN0eWxlPSJkaXNwbGF5Om5vbmUiey9pZn0+CgkJCQkJCSRzdWJuYXYKCQkJCQkJPC91bD4KCQkJCQkJPCEtLXsvaWZ9LS0+CgkJCQkJPCEtLXsvbG9vcH0tLT4KCQkJCTwhLS17L2lmfS0tPgoJCQkJPC9kaXY+CgkJCQk8IS0te2FkL3N1Ym5hdmJhbm5lci9hX211fS0tPgoJCQkJPCEtLXtzdWJ0ZW1wbGF0ZSBjb21tb24vcHVic2VhcmNoZm9ybX0tLT4KCQkJPC9kaXY+CgkJPC9kaXY+CgoJCTwhLS17aG9vay9nbG9iYWxfaGVhZGVyfS0tPgoJPCEtLXsvaWZ9LS0+CgoJPGRpdiBpZD0id3AiIGNsYXNzPSJ3cCI+Cg==
qidao123.com ToB IT社区-企服评测·应用市场»论坛 › 容器及微服务 › 容器及微服务 › K8s新手系列之ConfigMap资源
返回列表 发新帖

K8s新手系列之ConfigMap资源

[复制链接]
发表于 2025-5-2 22:08:29 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
概述

在 Kubernetes(K8s)中,ConfigMap 是一种 API 对象,用于将非机密性的数据生存到键值对中。Pod 可以将其用作环境变量、命令行参数或者存储卷中的配置文件。
ConfigMap 允许你将配置清单与镜像内容分离,以保持容器化的应用程序的可移植性。 例如,你可以下载并运行雷同的容器镜像来启动容器, 用于本地开发、体系测试或运行及时终端用户工作负载。
ConfigMap 是一个让你可以存储其他对象所需要使用的配置的 API 对象。 和其他 Kubernetes 对象都有一个 spec 不同的是,ConfigMap 使用 data 和 binaryData 字段。这些字段能够接收键-值对作为其取值。data 和 binaryData 字段都是可选的。data 字段设计用来生存 UTF-8 字符串,而 binaryData 则被设计用来生存二进制数据作为 base64 编码的字串。
官方文档地址:https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/configure-pod-configmap/
ConfigMap的作用

集中存储配置信息:


  • ConfigMap可以将应用程序的配置信息(如数据库毗连字符串、日志日志级别、服务端口等)集中存储在一个地方。这些配置信息以键值对的形式存在,方便管理和维护。例如,一个应用程序需要毗连到数据库,其数据库的用户名、密码、地址等信息可以存储在ConfigMap中。
  • 通过ConfigMap,开发者可以将配置信息与应用程序代码分离,使得应用程序更加通用和可移植。当需要在不同环境中运行应用程序时(如开发环境、测试环境和生产环境),只需修改ConfigMap中的配置值,而无需修改应用程序代码。
    支持多种数据格式
  • ConfigMap支持多种数据格式,包括字符串、文件内容等。可以将配置文件(如properties文件、yaml文件等)的内容直接存储到ConfigMap中。例如,一个应用程序的配置文件config.properties中包含多个配置项,可以将其内容读取后存储到ConfigMap中,然后应用程序通过ConfigMap来读取这些配置项。
注入配置

ConfigMap可以将配置信息注入到容器中,容器可以通过环境变量、挂载卷等方式访问这些配置信息。

  • 环境变量方式:可以将ConfigMap中的配置项作为环境变量注入到容器中。例如,一个容器需要访问数据库,其数据库的用户名和密码可以通过ConfigMap以环境变量的形式注入到容器中,容器在运行时可以直接使用这些环境变量来获取配置信息。
  • 挂载卷方式:可以将ConfigMap中的配置文件挂载到容器的文件体系中。例如,一个应用程序需要读取一个配置文件config.yaml,可以将存储该配置文件内容的ConfigMap挂载到容器的某个目录下,容器在运行时可以通过文件路径来访问该配置文件。
动态更新配置

当ConfigMap中的配置信息发生变化时,容器可以感知到这些变化,并根据需要重新加载配置信息。这种动态更新配置的能力使得应用程序可以在不重启容器的情况下,快速响应配置的变化。例如,当数据库的毗连地址发生变化时,更新ConfigMap中的相应配置项,容器可以自动获取新的配置并重新建立数据库毗连。
进步代码的可维护性

将配置信息存储在ConfigMap中,使得应用程序代码更加简便和清楚。开发者不需要在代码中硬编码配置信息,减少了代码的复杂性和耦合度。当需要修改配置时,只需修改ConfigMap,而无需修改代码,降低了维护成本。
加强代码的可移植性

由于配置信息与代码分离,应用程序可以在不同的环境中运行,而无需修改代码。通过调整ConfigMap中的配置值,可以轻松地将应用程序从开发环境迁移到测试环境或生产环境,进步了应用程序的可移植性。
多容器共享配置

在 Kubernetes 中,一个ConfigMap可以被多个容器共享。当多个容器需要使用雷同的配置信息时,可以使用同一个ConfigMap,避免了重复配置的题目。例如,在一个微服务架构中,多个服务实例可能需要访问同一个数据库,可以将数据库的配置信息存储在一个ConfigMap中,所有服务实例都可以通过该ConfigMap来获取配置信息。
多应用共享配置

不同的应用程序也可以共享同一个ConfigMap。例如,多个应用程序可能需要访问同一个外部服务,可以将该外部服务的配置信息存储在一个ConfigMap中,所有应用程序都可以通过该ConfigMap来获取配置信息。
简化部署流程

在部署应用程序时,通过ConfigMap可以快速地将配置信息传递给容器。开发者只需定义好ConfigMap,然后在部署时将ConfigMap与容器关联起来,即可完成配置的注入,简化了部署流程。
方便运维管理

运维职员可以通过ConfigMap集中管理配置信息,方便对配置进行修改、备份和恢复。当出现题目时,可以通过查看ConfigMap中的配置信息来快速定位题目原因,进步了运维效率。
创建ConfigMap

通过文件来创建ComfigMap

语法:
  1. kubectl create configmap [config的名称] --from-file=[file] ... --from-file=[file]
  2. # 或者通过
  3. kubectl create configmap [config的名称] --from-env-file=[file] ... --from-env-file=[file]
  4. 解析:
  5. --from-env-file:可以通过env的方式来创建ConfigMap,例如name=zhangsan,使用--from-file创建时,其配置项不会变化。
  6. 但是通过--from-env-file创建时,会自动解析成name: zhangsan的形式
复制代码
哪些文件可以用来创建ConfigMap呢?


  • .properties文件:这是 Java 应用常用的配置文件类型,采用键值对的格式存储配置信息,例如:
  1. database.host=localhost
  2. database.port=3306
复制代码

  • .yaml/.yml文件:是一种可读性高的数据序列化格式,在 Kubernetes 自身配置和很多应用配置中广泛使用,例如:
  1. database:
  2.   host: localhost
  3.   port: 3306
  4. server:
  5.   port: 8080
复制代码

  • .ini 文件:常用于存储配置数据,其结构包含多个节(section),每个节下面有多个键值对,示例如下:
  1. [database]
  2. host=localhost
  3. port=3306
  4. [server]
  5. port=8080
复制代码

  • .json 文件:一种轻量级的数据互换格式,常用于存储结构化数据,示例如下:
  1. {
  2.   "database": {
  3.     "host": "localhost",
  4.     "port": 3306
  5.   },
  6.   "server": {
  7.     "port": 8080
  8.   }
  9. }
复制代码

  • .conf 文件:通常是各种服务的配置文件,像 Nginx、Apache 等服务的配置文件就常以 .conf 为扩展名。
  1. worker_processes auto;
  2. error_log /var/log/nginx/error.log warn;
  3. pid /var/run/nginx.pid;
  4. events {
  5.     worker_connections 1024;
  6. }
  7. http {
  8.     server {
  9.     }
  10. }
复制代码

  • .txt文件:普通文本文件,可存储任意文本信息,例如存储日志日志级别、应用形貌等内容。
  1. asdsxfaseqwesd
复制代码
通过properties文件创建ConfigMap

示例:
  1. # 创建properties文件
  2. [root@master01 ~/configmap]# cat db.properties
  3. database.url=jdbc:mysql://localhost:3306/mydb
  4. database.username=root
  5. database.password=password
  6. # 创建ComfigMap
  7. [root@master01 ~/configmap]# kubectl create configmap db-config --from-file=db.properties
  8. configmap/db-config created
  9. # 查看ConfigMap
  10. [root@master01 ~/configmap]# kubectl get configmap
  11. NAME               DATA   AGE
  12. db-config          1      53s
  13. # 查看ConfigMap生成的yaml文件
  14. [root@master01 ~/configmap]# kubectl get configmap db-config -o yaml
  15. apiVersion: v1
  16. metadata:
  17.   creationTimestamp: "2025-05-02T06:02:42Z"
  18.   name: db-config
  19.   namespace: default
  20.   resourceVersion: "59760"
  21.   uid: dc9de3eb-5e19-47fd-854d-2c4fcddbf8ba
  22. data:
  23.   db.properties: |
  24.     database.url=jdbc:mysql://localhost:3306/mydb
  25.     database.username=root
  26.     database.password=password
  27. kind: ConfigMap
  28. # 查看ConfigMap的详细信息
  29. [root@master01 ~/configmap]# kubectl describe configmap db-config
  30. Name:         db-config
  31. Namespace:    default
  32. Labels:       <none>
  33. Annotations:  <none>
  34. Data #这里就是对应的数据信息
  35. ====
  36. db.properties:
  37. ----
  38. database.url=jdbc:mysql://localhost:3306/mydb
  39. database.username=root
  40. database.password=password
  41. BinaryData #这里是二进制数据
  42. ====
  43. Events:  <none>
复制代码
通过目录创建ConfigMap

语法:
  1. kubectl create configmap [config的名称] --from-file=[filepath] ... --from-file=[filepath]
  2. # 或者通过
  3. kubectl create configmap [config的名称] --from-env-file=[filepath] ... --from-env-file=[filepath]
  4. 解析:
  5. --from-env-file:可以通过env的方式来创建ConfigMap,例如name=zhangsan,使用--from-file创建时,其配置项不会变化。
  6. 但是通过--from-env-file创建时,会自动解析成name: zhangsan的形式
复制代码
这种方式其实和通过文件来创建ConfigMap是一样的原理。
示例:
  1. # 创建目录
  2. [root@master01 ~]# mkdir -p /root/configmap/app
  3. # 造数据
  4. [root@master01 ~]# wget https://kubernetes.io/examples/configmap/game.properties -O /root/configmap/app/game.properties
  5. #...省略部分信息
  6. /root/configmap/app/game.properties                 100%[==================================================================================================================>]     157  --.-KB/s    in 0s
  7. 2025-05-02 14:09:46 (178 MB/s) - ‘/root/configmap/app/game.properties’ saved [157/157]
  8. [root@master01 ~]# wget https://kubernetes.io/examples/configmap/ui.properties -O /root/configmap/app/ui.properties
  9. #...省略部分信息
  10. /root/configmap/app/ui.properties                   100%[==================================================================================================================>]      83  --.-KB/s    in 0s
  11. 2025-05-02 14:10:03 (156 MB/s) - ‘/root/configmap/app/ui.properties’ saved [83/83]
  12. # 创建ConfigMap
  13. [root@master01 ~]# kubectl create configmap app-config  --from-file=/root/configmap/app
  14. configmap/app-config created
  15. # 查看ConfigMap,两个文件变成了一个configMap
  16. [root@master01 ~]# kubectl get configmap app-config -o yaml
  17. apiVersion: v1
  18. kind: ConfigMap
  19. metadata:
  20.   creationTimestamp: "2025-05-02T06:13:01Z"
  21.   name: app-config
  22.   namespace: default
  23.   resourceVersion: "61185"
  24.   uid: 2cce2598-db6f-41a2-89fe-f144fac4159c
  25. data:
  26.   game.properties: |-
  27.     enemies=aliens
  28.     lives=3
  29.     enemies.cheat=true
  30.     enemies.cheat.level=noGoodRotten
  31.     secret.code.passphrase=UUDDLRLRBABAS
  32.     secret.code.allowed=true
  33.     secret.code.lives=30
  34.   ui.properties: |
  35.     color.good=purple
  36.     color.bad=yellow
  37.     allow.textmode=true
  38.     how.nice.to.look=fairlyNice
复制代码
通过字面量创建ConfigMap

ConfigMap还支持直接输入字面量来创建
语法:
  1. kubectl create configmap [configName] [--from-literal="key=value"] ... [--from-literal="key=value"]
复制代码
示例:
  1. # 创建ConfigMap
  2. [root@master01 ~]# kubectl create configmap user-config --from-literal="user.name=zhangsan" \
  3.                                       --from-literal="user.age=18" \
  4.                                       --from-literal="user.addr=beijing"
  5. configmap/user-config created
  6. # 查看ConfigMap的yaml文件
  7. [root@master01 ~]# kubectl get configmap user-config -o yaml
  8. apiVersion: v1
  9. kind: ConfigMap
  10. metadata:
  11.   creationTimestamp: "2025-05-02T06:35:22Z"
  12.   name: user-config
  13.   namespace: default
  14.   resourceVersion: "64263"
  15.   uid: 9ffe4dc3-31ee-4cde-bbfe-24041aa824bd
  16. data:
  17.   user.addr: beijing
  18.   user.age: "18"
  19.   user.name: zhangsan
  20. # 查看详细信息
  21. [root@master01 ~]# kubectl describe configmap user-config
  22. Name:         user-config
  23. Namespace:    default
  24. Labels:       <none>
  25. Annotations:  <none>
  26. Data
  27. ====
  28. user.age:
  29. ----
  30. 18
  31. user.name:
  32. ----
  33. zhangsan
  34. user.addr:
  35. ----
  36. beijing
  37. BinaryData
  38. ====
  39. Events:  <none>
复制代码
通过资源清单创建ConfigMap

ConfigMap也可以通过K8s的Yaml文件进行创建,通过资源清单创建ConfigMap有两种方式,一种是类属性键,一种是类文件键
示例:
  1. # 定义资源清单
  2. [root@master01 ~/configmap]# cat game-configmap.yaml
  3. apiVersion: v1
  4. kind: ConfigMap
  5. metadata:
  6.   name: game-demo
  7. data:
  8.   # 类属性键;每一个键都映射到一个简单的值
  9.   player_initial_lives: "3"
  10.   ui_properties_file_name: "user-interface.properties"
  11.   # 类文件键
  12.   game.properties: |
  13.     enemy.types=aliens,monsters
  14.     player.maximum-lives=5
  15.   nginx.conf: |
  16.         server {
  17.             listen:80;
  18.             server_name:xxx;
  19.             root:/root;
  20.             location:{
  21.                 xxx
  22.             }
  23.         }
  24. # 创建configMap
  25. [root@master01 ~/configmap]# kubectl apply -f game-configmap.yaml
  26. configmap/game-demo created
  27. # 查看yaml文件
  28. [root@master01 ~/configmap]# kubectl get configmap game-demo -o yaml
  29. apiVersion: v1
  30. kind: ConfigMap
  31. metadata:
  32.   annotations:
  33.     kubectl.kubernetes.io/last-applied-configuration: |
  34.       {"apiVersion":"v1","data":{"game.properties":"enemy.types=aliens,monsters\nplayer.maximum-lives=5\n","nginx.conf":"server {\n    listen:80;\n    server_name:xxx;\n    root:/root;\n    location:{\n        xxx\n    }\n}\n","player_initial_lives":"3","ui_properties_file_name":"user-interface.properties"},"kind":"ConfigMap","metadata":{"annotations":{},"name":"game-demo","namespace":"default"}}
  35.   creationTimestamp: "2025-05-02T06:48:39Z"
  36.   name: game-demo
  37.   namespace: default
  38.   resourceVersion: "66094"
  39.   uid: d2f71bfb-5a8d-4cd4-b9fc-b490aef77f67
  40. data:
  41.   game.properties: |
  42.     enemy.types=aliens,monsters
  43.     player.maximum-lives=5
  44.   nginx.conf: |
  45.     server {
  46.         listen:80;
  47.         server_name:xxx;
  48.         root:/root;
  49.         location:{
  50.             xxx
  51.         }
  52.     }
  53.   player_initial_lives: "3"
  54.   ui_properties_file_name: user-interface.properties
  55. # 查看详细信息
  56. [root@master01 ~/configmap]# kubectl describe cm game-demo
  57. Name:         game-demo
  58. Namespace:    default
  59. Labels:       <none>
  60. Annotations:  <none>
  61. Data
  62. ====
  63. nginx.conf:
  64. ----
  65. server {
  66.     listen:80;
  67.     server_name:xxx;
  68.     root:/root;
  69.     location:{
  70.         xxx
  71.     }
  72. }
  73. player_initial_lives:
  74. ----
  75. 3
  76. ui_properties_file_name:
  77. ----
  78. user-interface.properties
  79. game.properties:
  80. ----
  81. enemy.types=aliens,monsters
  82. player.maximum-lives=5
  83. BinaryData
  84. ====
  85. Events:  <none>
复制代码
修改ConfigMap的值

ConfigMap无法修改名称,但是可以修改其值
通过kubectl方式修改

可以通过kubectl edit configmap configmapname来进行修改其值,使用kubectl命令之后,会打开一个雷同vim的编辑界面,修改之后使用:wq生存之后即可
通过文件修改

修改了资源文件之后,configmap雷同的key会进行覆盖,不同的key会进行添加,并不会进行删除多余的key
查看ConfigMap
  1. # 查看所有的ConfigMap
  2. [root@master01 ~]# kubectl get configmap -A
  3. NAMESPACE          NAME                                 DATA   AGE
  4. calico-apiserver   kube-root-ca.crt                     1      6d6h
  5. calico-system      active-operator                      1      6d6h
  6. calico-system      cni-config                           1      6d6h
  7. calico-system      kube-root-ca.crt                     1      6d6h
  8. calico-system      tigera-ca-bundle                     2      6d6h
  9. default            app-config                           2      4h39m
  10. default            db-config                            1      6h13m
  11. default            env-config                           3      5h17m
  12. # 查看指定命名空间下的ConfigMap
  13. [root@master01 ~]# kubectl get configmap -n calico-system
  14. NAME               DATA   AGE
  15. active-operator    1      6d6h
  16. cni-config         1      6d6h
  17. kube-root-ca.crt   1      6d6h
  18. tigera-ca-bundle   2      6d6h
  19. # 以yaml文件查看
  20. [root@master01 ~]# kubectl get configmap db-config -o yaml
  21. apiVersion: v1
  22. kind: ConfigMap
  23. metadata:
  24.   creationTimestamp: "2025-05-02T06:02:42Z"
  25.   name: db-config
  26.   namespace: default
  27.   resourceVersion: "59760"
  28.   uid: dc9de3eb-5e19-47fd-854d-2c4fcddbf8ba
  29. data:
  30.   db.properties: |
  31.     database.url=jdbc:mysql://localhost:3306/mydb
  32.     database.username=root
  33.     database.password=password
复制代码
删除ConfigMap

使用kubectl delete configmap [name1 name2 ... nameN]的方式删除即可
示例:
  1. [root@master01 ~]# kubectl delete configmap db-config
  2. configmap "db-config" deleted
  3. # 验证是否删除成功
  4. [root@master01 ~]# kubectl get configmap db-config
  5. Error from server (NotFound): configmaps "db-config" not found
复制代码
配置Pod使用ConfigMap

Pod使用ConfigMap资源,有两种方式,一种是通过环境变量的方式使用,另一种方式通过数据卷挂载的方式使用
留意:

  • 静态Pod不能使用ConfigMap
  • Pod 和 ConfigMap 必须要在同一个namespace中。
Pod通过环境变量使用ConfigMap

示例:
先创建ConfigMap
  1. # 创建ConfigMap
  2. [root@master01 ~]# echo 'apiVersion: v1
  3. kind: ConfigMap
  4. metadata:
  5.   name: special-config
  6. data:
  7.   USER_NAME: huangsir
  8.   APP: haha
  9.   COLOR: red
  10. ---
  11. apiVersion: v1
  12. kind: ConfigMap
  13. metadata:
  14.   name: env-config
  15.   namespace: default
  16. data:
  17.   USER_AGE: "18"
  18.   USER_NAME: zhangsan
  19.   USER_ADDR: beijing' | kubectl apply -f -
复制代码
将 ConfigMap 的内容用作Pod的环境变量:
  1. # 创建Pod
  2. [root@master01 ~/configmap]# echo 'apiVersion: v1
  3. kind: Pod
  4. metadata:
  5.   name: env-configmap-pod
  6. spec:
  7.   containers:
  8.     - name: app
  9.       # 打印环境变量
  10.       command: ["/bin/sh", "-c", "printenv"]
  11.       image: busybox:latest
  12.       # 指定env来自哪里
  13.       envFrom:
  14.         # 配置ConfigMap的引用
  15.         - configMapRef:
  16.             # 指定要引用的ConfigMap的名称
  17.             name: env-config' | kubectl apply -f -
  18. # 查看Pod的日志日志是否打印出配置的环境变量
  19. [root@master01 ~/configmap]# kubectl logs env-configmap-pod | grep USER
  20. USER_ADDR=beijing
  21. USER_AGE=18
  22. USER_NAME=zhangsan
复制代码
指定Pod的环境变量为ConfigMap中的Key

示例:
  1. # 创建Pod
  2. echo 'apiVersion: v1
  3. kind: Pod
  4. metadata:
  5.   name: env-configmap-pod-1
  6. spec:
  7.   containers:
  8.     - name: app
  9.       # 打印环境变量
  10.       command: ["/bin/sh", "-c", "printenv"]
  11.       image: busybox:latest
  12.       env:
  13.       # 指定Pod中环境变量的key
  14.       - name: POD-NAME
  15.         # 指定环境变量的value从哪里获取
  16.         valueFrom:
  17.           # 指定从ConfigMap中获取
  18.           configMapKeyRef:
  19.             # 指定ConfigMap的名称
  20.             name: special-config
  21.             # 指定ConfigMap中存在key
  22.             key: USER_NAME
  23.       # 可以定义多个值
  24.       - name: POD-ADDR
  25.         valueFrom:
  26.           configMapKeyRef:
  27.             name: env-config
  28.             key: USER_ADDR' | kubectl apply -f -
  29. # 查看日志中打印的环境变量
  30. [root@master01 ~/configmap]# kubectl logs env-configmap-pod-1 | grep POD
  31. POD-ADDR=beijing
  32. POD-NAME=huangsir
复制代码
Pod通过存储卷挂载使用ConfigMap的方式

创建ConfigMap
  1. [root@master01 ~/configmap]# echo 'apiVersion: v1
  2. kind: ConfigMap
  3. metadata:
  4.   name: app-config
  5. data:
  6.   config.properties: |
  7.     database.url=jdbc:mysql://localhost:3306/mydb
  8.     database.username=root
  9.     database.password=password
  10.   log.properties: |
  11.     log.level=INFO
  12.     log.file=/var/log/app.log' | kubectl apply -f -
复制代码
创建Pod挂载ConfigMap

方式一:将ConfigMap中所有的Key挂载到Pod指定的路径下,这种方式有以下几个地方需要留意:

  • 如果Pod挂载所在的目录中有别的的文件或目录,会将其删除
  • 如果指定Pod挂载的目录不存在,会自动创建
  • 挂载时会自动创建对应ConfigMap中的文件
示例:
  1. # 创建Pod
  2. echo 'apiVersion: v1
  3. kind: Pod
  4. metadata:
  5.   name: volume-pod-1
  6. spec:
  7.   containers:
  8.     - name: app
  9.       image: nginx:latest
  10.       # 存储卷挂载到本地
  11.       volumeMounts:
  12.       # Pod存储卷挂载的名称
  13.       - name: config-volume
  14.         mountPath: /etc/config
  15.   volumes:
  16.   - name: config-volume
  17.     # 存储卷挂载的类型
  18.     configMap:
  19.       name: app-config' | kubectl apply -f -
  20.           
  21. # 验证挂载路径
  22. [root@master01 ~/configmap]# kubectl exec -it volume-pod-1 -- ls -l /etc/config
  23. total 0
  24. lrwxrwxrwx 1 root root 24 May  2 07:50 config.properties -> ..data/config.properties
  25. lrwxrwxrwx 1 root root 21 May  2 07:50 log.properties -> ..data/log.properties
复制代码
如果只想挂载ConfigMap中的部门键,而且指定挂载到Pod中的文件名,可以使用items和subPath字段来实现
示例:
  1. # 创建Pod
  2. [root@master01 ~/configmap]# echo 'apiVersion: v1
  3. kind: Pod
  4. metadata:
  5.   name: volume-pod-2
  6. spec:
  7.   containers:
  8.     - name: app
  9.       image: nginx:latest
  10.       # 存储卷挂载到本地
  11.       volumeMounts:
  12.       # Pod存储卷挂载的名称
  13.       - name: config-volume
  14.         mountPath: /etc/config/log-custom.properties
  15.         # 当使用subPath属性时,则mountPath执行的不是目录,而是文件
  16.         # 必要条件:一定要让subPath的值和items列表中的path值相同
  17.         subPath: log-custom.properties
  18.   volumes:
  19.   - name: config-volume
  20.     # 存储卷挂载的类型
  21.     configMap:
  22.       name: app-config
  23.       items:
  24.       - key: log.properties
  25.         path: log-custom.properties' | kubectl apply -f -
  26. # 验证
  27. [root@master01 ~/configmap]# kubectl exec -it volume-pod-2 -- cat /etc/config/log-custom.properties
  28. log.level=INFO
  29. log.file=/var/log/app.log
复制代码
配置不可变更的 ConfigMap

Kubernetes v1.21的版本中提供了一种将各个 Secret 和 ConfigMap 设置为不可变更的选项。
对于大量使用 ConfigMap 的集群 (至少有数万个各不雷同的 ConfigMap 给 Pod 挂载)而言,禁止更改 ConfigMap 的数据有以下利益:

  • 保护应用,使之免受不测(不想要的)更新所带来的负面影响。
  • 通过大幅降低对 kube-apiserver 的压力提升集群性能, 这是由于体系会关闭对已标记为不可变更的 ConfigMap 的监视操纵。
实现方式:
  1. # 通过将 immutable 字段设置为 true 创建不可变更的 ConfigMap
  2. apiVersion: v1
  3. kind: ConfigMap
  4. metadata:
  5.   ...
  6. data:
  7.   ...
  8. immutable: true
复制代码
一旦某 ConfigMap 被标记为不可变更,则 无法 逆转这一变化,也无法更改 data 或 binaryData 字段的内容。你只能删除并重建 ConfigMap。 由于现有的 Pod 会维护一个已被删除的 ConfigMap 的挂载点,发起重新创建这些 Pods。
挂载的 ConfigMap 内容会被自动更新

当Pod中使用的 ConfigMap 被更新时,所对应的Pod中对应Key也会被更新。
kubelet 组件会在每次周期性同步时查抄所挂载的 ConfigMap 是否为最新。不过,kubelet 使用的是其本地的高速缓存来得到 ConfigMap 的当前值。 高速缓存的类型可以通过 KubeletConfiguration.configMapAndSecretChangeDetectionStrategy 字段来配置。
留意以下两种方式不会被更新,需要重启Pod:

  • 以环境变量方式使用的 ConfigMap 数据不会被自动更新。
  • 使用 ConfigMap 作为 subPath 卷挂载的容器将不会收到 ConfigMap 的更新。
示例:以上述Pod通过存储卷挂载使用ConfigMap的方式来验证
  1. # 修改ConfigMap前的挂载内容
  2. # pod1的内容,以普通数据卷的挂载方式
  3. [root@master01 ~]# kubectl exec -it volume-pod-1 -- cat /etc/config/log.properties
  4. log.level=INFO
  5. log.file=/var/log/app.log
  6. # pod2的内容,以subPath的挂载方式
  7. [root@master01 ~]# kubectl exec -it volume-pod-2 -- cat /etc/config/log-custom.properties
  8. log.level=INFO
  9. log.file=/var/log/app.log
  10. # 修改ConfigMap
  11. [root@master01 ~]# echo 'apiVersion: v1
  12. kind: ConfigMap
  13. metadata:
  14.   name: app-config
  15. data:
  16.   config.properties: |
  17.     database.url=jdbc:mysql://localhost:3306/mydb
  18.     database.username=root
  19.     database.password=password
  20.   log.properties: |
  21.     log.level=error
  22.     log.file=/var/log/error.log' | kubectl apply -f -
  23. # 验证是否修改成功
  24. [root@master01 ~]# kubectl describe cm app-config
  25. Name:         app-config
  26. Namespace:    default
  27. Labels:       <none>
  28. Annotations:  <none>
  29. Data
  30. ====
  31. config.properties:
  32. ----
  33. database.url=jdbc:mysql://localhost:3306/mydb
  34. database.username=root
  35. database.password=password
  36. log.properties:
  37. ----
  38. log.level=error
  39. log.file=/var/log/error.log
  40. BinaryData
  41. ====
  42. Events:  <none>
  43. # 验证Pod内部是否自动更新
  44. # pod1更新成功,
  45. [root@master01 ~]# kubectl exec -it volume-pod-1 -- cat /etc/config/log.properties
  46. log.level=error
  47. log.file=/var/log/error.log
  48. # pod2未更新
  49. [root@master01 ~]# kubectl exec -it volume-pod-2 -- cat /etc/config/log-custom.properties
  50. log.level=INFO
  51. log.file=/var/log/app.log
复制代码
回复

使用道具 举报

返回列表 发新帖
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录

QQ|手机版|qidao123.com IT社区;IT企服评测▪应用市场 ( 浙ICP备20004199|浙ICP备20004199号 )|网站地图

GMT+8, 2026-10-2 01:13 , Processed in 0.025876 second(s), 6 queries , Redis On.

Powered by Discuz! X3.5 Licensed

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表